1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Portions of this software have been released under the following terms: 31 * 32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. 33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY 34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION 35 * 36 * To anyone who acknowledges that this file is provided "AS IS" 37 * without any express or implied warranty: 38 * permission to use, copy, modify, and distribute this file for any 39 * purpose is hereby granted without fee, provided that the above 40 * copyright notices and this notice appears in all source code copies, 41 * and that none of the names of Open Software Foundation, Inc., Hewlett- 42 * Packard Company or Digital Equipment Corporation be used 43 * in advertising or publicity pertaining to distribution of the software 44 * without specific, written prior permission. Neither Open Software 45 * Foundation, Inc., Hewlett-Packard Company nor Digital 46 * Equipment Corporation makes any representations about the suitability 47 * of this software for any purpose. 48 * 49 * Copyright (c) 2007, Novell, Inc. All rights reserved. 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in the 58 * documentation and/or other materials provided with the distribution. 59 * 3. Neither the name of Novell Inc. nor the names of its contributors 60 * may be used to endorse or promote products derived from this 61 * this software without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY 67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 73 * 74 * @APPLE_LICENSE_HEADER_END@ 75 */ 76 77/* 78** 79** NAME: 80** 81** dgclsn.c 82** 83** FACILITY: 84** 85** Remote Procedure Call (RPC) 86** 87** ABSTRACT: 88** 89** DG protocol service routines. Client-oriented routines that run in the 90** listener thread. 91** 92** 93*/ 94 95#include <dg.h> 96#include <dgxq.h> 97#include <dgclsn.h> 98#include <dgcall.h> 99 100INTERNAL boolean32 chk_sboot ( 101 rpc_dg_recvq_elt_p_t /*rqe*/, 102 rpc_dg_ccall_p_t /*ccall*/ 103 ); 104 105INTERNAL void do_quack_body ( 106 rpc_dg_recvq_elt_p_t /*rqe*/, 107 rpc_dg_ccall_p_t /*ccall*/ 108 ); 109 110/* ========================================================================= */ 111 112/* 113 * C H K _ S B O O T 114 * 115 * Server boot time processing / verification. Checks that a received 116 * packet is from the same instance of the server as previously received 117 * packets for this call. This function is used in all server->client 118 * packet type managers. 119 */ 120 121INTERNAL boolean32 chk_sboot 122( 123 rpc_dg_recvq_elt_p_t rqe, 124 rpc_dg_ccall_p_t ccall 125) 126{ 127 if (ccall->c.call_server_boot != 0 && 128 rqe->hdrp->server_boot != ccall->c.call_server_boot) 129 { 130 RPC_DBG_GPRINTF(("s->c Server boot time mismatch [%s]\n", 131 rpc__dg_act_seq_string(rqe->hdrp))); 132 rpc__dg_call_signal_failure(&ccall->c, rpc_s_wrong_boot_time); 133 return (false); 134 } 135 else 136 { 137 return (true); 138 } 139} 140 141/* 142 * R P C _ _ D G _ D O _ C O M M O N _ R E S P O N S E 143 * 144 * Provide processing common for receipt of response, reject, fault, and 145 * quack packets. 146 * 147 * Returns: false - if the packet should be discarded (old or a duplicate). 148 * true - otherwise 149 * 150 */ 151 152PRIVATE boolean rpc__dg_do_common_response 153( 154 rpc_dg_sock_pool_elt_p_t sp, 155 rpc_dg_recvq_elt_p_t rqe, 156 rpc_dg_ccall_p_t ccall 157) 158{ 159 rpc_dg_pkt_hdr_p_t hdrp = rqe->hdrp; 160 rpc_dg_ptype_t ptype = RPC_DG_HDR_INQ_PTYPE(hdrp); 161 unsigned32 st; 162 163 /* 164 * Make sure the packet is for the current call. Note: the sequence 165 * number may be greater than our current one due to proxy calls. 166 * 167 * Response packet considerations: 168 * If we're in a call and this response is for an old call, send 169 * an "ack" just in case the activity ID has been reused on a call 170 * to a different server. If the response is to a previous call 171 * then assume that an "ack" was lost and resend it. (Note that 172 * we will only resend an ACK on receipt of the last, or only, fragment 173 * of a response; we do this because when an ACK is lost, the server 174 * will retransmit the last blast's worth of data and we don't want 175 * to send ACKs for each one.) Duplicate "ack"s are not a problem 176 * because servers will simply ignore them. Note that the seq number 177 * can actually be greater than the current call's sequence due to 178 * proxy calls. 179 * 180 * Fault packet considerations: 181 * If the fault is to a previous call it may be a duplicate, however, 182 * it may also be a valid fault packet that has not been "ack"ed. 183 * Valid fault packets may result from activity ID's being rapidly 184 * reused after an "ack" has been lost. Also, the packet may be 185 * for this call and we may already be in an error state which may 186 * have been because we've already received a fault but for some 187 * reason we haven't completed the call yet. The proper action in 188 * all three of the above cases is to send an "ack" to stop the server 189 * from resending the fault. Any extra "ack"s will be ignored by 190 * the server. Note that the seq number can actually be greater 191 * than the current call's sequence due to proxy calls. 192 */ 193 194 if (ccall == NULL 195 || RPC_DG_SEQ_IS_LT(hdrp->seq, ccall->c.call_seq) 196 || (ptype == RPC_C_DG_PT_FAULT && ccall->fault_rqe != NULL) 197 || (ptype == RPC_C_DG_PT_WORKING && ccall->c.state != rpc_e_dg_cs_recv)) 198 { 199 if (ptype == RPC_C_DG_PT_FAULT || 200 (ptype == RPC_C_DG_PT_RESPONSE && 201 (! RPC_DG_HDR_FLAG_IS_SET(hdrp, RPC_C_DG_PF_FRAG) || 202 RPC_DG_HDR_FLAG_IS_SET(hdrp, RPC_C_DG_PF_LAST_FRAG)))) 203 { 204 rpc__dg_xmit_hdr_only_pkt(sp->sock, (rpc_addr_p_t) &rqe->from, 205 rqe->hdrp, RPC_C_DG_PT_ACK); 206 } 207 RPC_DBG_PRINTF(rpc_e_dbg_recv, 1, 208 ("(rpc__dg_do_common_response) Dropped %s [%s]\n", 209 rpc__dg_pkt_name(ptype), rpc__dg_act_seq_string(rqe->hdrp))); 210 return (false); 211 } 212 213 RPC_DG_CALL_LOCK_ASSERT(&ccall->c); 214 215 /* 216 * If the call has been orphaned, our interest in various pkt types 217 * is lessened. 218 */ 219 220 if (ccall->c.state == rpc_e_dg_cs_orphan 221 && (ptype == RPC_C_DG_PT_RESPONSE || ptype == RPC_C_DG_PT_FACK)) 222 { 223 RPC_DBG_PRINTF(rpc_e_dbg_general, 4, 224 ("(rpc__dg_do_common_response) Call failed or orphaned, Dropped %s [%s]\n", 225 rpc__dg_pkt_name(ptype), rpc__dg_act_seq_string(rqe->hdrp))); 226 return (false); 227 } 228 229 /* 230 * If all the packets has been received for this call, we don't have to 231 * do any more work here (in particular, we don't want to check the boot 232 * time since in the case of broadcast, we don't want to get upset by 233 * responses from other servers which will of course have different 234 * boot times). 235 */ 236 237 if (ccall->c.rq.all_pkts_recvd) 238 return (false); 239 240 if (! chk_sboot(rqe, ccall)) 241 { 242 return (false); 243 } 244 245 /* 246 * There are several interesting and / or necessary pieces of 247 * information that we need to snag from a response packet header. 248 * Pick up the hints and the response sequence number (to properly 249 * manage our sequence number space in the presence of proxy calls). 250 * 251 * Now that we've successfully "(re)connected" to the server we also 252 * reset the call's com_timeout_knob to be no lower than the default 253 * timeout level. 254 */ 255 256 if (! ccall->response_info_updated) 257 { 258 ccall->response_info_updated = true; 259 ccall->c.call_ahint = hdrp->ahint; 260 ccall->c.call_ihint = hdrp->ihint; 261 262 ccall->c.com_timeout_knob = MAX(ccall->c.com_timeout_knob, 263 rpc_c_binding_default_timeout); 264 } 265 266 /* 267 * We need to pick update the high_seq (highest proxy call seq) info 268 * from the response stream. Logically, we only need to get this 269 * info for the last pkt of the response stream, however, it's 270 * easier to always pick it up and just make certain that we 271 * don't allow it to go backwards (without this check it can 272 * go backwards, trust me). 273 */ 274 275 if (RPC_DG_SEQ_IS_LT(ccall->c.high_seq,hdrp->seq)) 276 ccall->c.high_seq = hdrp->seq; 277 278 /* 279 * Update our server address binding if necessary. Also, 280 * if we're are updating the remote address being used for 281 * this conversation, we must also call the NAF routine to 282 * to determine the max_path_tpdu for this path. 283 */ 284 285 if (! ccall->server_bound) 286 { 287 ccall->server_bound = true; 288 ccall->c.call_server_boot = hdrp->server_boot; 289 rpc__naf_addr_overcopy((rpc_addr_p_t) &rqe->from, &ccall->c.addr, &st); 290 291 if ((ccall->c.xq.base_flags & RPC_C_DG_PF_BROADCAST) != 0) 292 { 293 RPC_DG_CALL_SET_MAX_FRAG_SIZE(&ccall->c, &st); 294 295 RPC_DG_RBUF_SIZE_TO_WINDOW_SIZE(sp->rcvbuf, 296 sp->is_private, 297 ccall->c.xq.max_frag_size, 298 ccall->c.rq.window_size); 299 RPC_DBG_PRINTF(rpc_e_dbg_recv, 7, 300 ("(rpc__dg_do_common_response) Set ws %d, rcvbuf %u, max fs %u\n", 301 ccall->c.rq.window_size, sp->rcvbuf, ccall->c.xq.max_frag_size)); 302 } 303 } 304 305 /* 306 * Update the call's had_pending state with the information in the response. 307 * This is really only necesssary on the last pkt of a response, but it's 308 * probably cheaper to always do it. Ensure that once a "had_pending" 309 * state is detected, it stays that way. 310 */ 311 312 if (RPC_DG_HDR_FLAG2_IS_SET(hdrp, RPC_C_DG_PF2_CANCEL_PENDING)) 313 { 314 if (!ccall->cancel.server_had_pending) 315 { 316 RPC_DBG_PRINTF(rpc_e_dbg_cancel, 10, 317 ("(rpc__dg_do_common_response) setting cancel_pending\n")); 318 } 319 ccall->cancel.server_had_pending = true; 320 } 321 322 return (true); 323} 324 325/* 326 * R P C _ _ D G _ D O _ R E J E C T 327 * 328 * Handle a call reject packet 329 * 330 * Signal a call failure with the appropriate status. 331 */ 332 333PRIVATE boolean rpc__dg_do_reject 334( 335 rpc_dg_sock_pool_elt_p_t sp, 336 rpc_dg_recvq_elt_p_t rqe, 337 rpc_dg_ccall_p_t ccall 338) 339{ 340 unsigned32 mst; 341 342 /* 343 * Perform common response packet processing. 344 */ 345 346 if (! rpc__dg_do_common_response(sp, rqe, ccall)) 347 return (RPC_C_DG_RDF_FREE_RQE); 348 349 RPC_DBG_GPRINTF(("(rpc__dg_do_reject) Got a live one [%s]\n", 350 rpc__dg_act_seq_string(rqe->hdrp))); 351 352 RPC_DG_CALL_LOCK_ASSERT(&ccall->c); 353 354 /* 355 * When in the orphan state, a reject is just as good as a quack. 356 */ 357 358 if (ccall->c.state == rpc_e_dg_cs_orphan) 359 { 360 ccall->quit.quack_rcvd = true; 361 rpc__dg_call_signal(&ccall->c); 362 return (RPC_C_DG_RDF_FREE_RQE); 363 } 364 365 /* 366 * Free any packets we have on the transmit queue still since the 367 * fault is (implicitly) ack'ing them. 368 */ 369 370 if (ccall->c.xq.head != NULL) 371 rpc__dg_xmitq_free(&ccall->c.xq, &ccall->c); 372 373 /* 374 * A reject response terminates the OUTs data stream. 375 */ 376 377 ccall->c.rq.all_pkts_recvd = true; 378 379 /* 380 * Get the NCA status from the reject packet body and map it to a local 381 * status code. Blow off the call with this mapped status. 382 */ 383 384 rpc__dg_get_epkt_body_st(rqe, &ccall->reject_status); 385 386 switch ((int)ccall->reject_status) 387 { 388 case nca_s_comm_failure: mst = rpc_s_comm_failure; break; 389 case nca_s_unk_if: mst = rpc_s_unknown_if; break; 390 case nca_s_unsupported_type: mst = rpc_s_unsupported_type; break; 391 case nca_s_manager_not_entered: mst = rpc_s_manager_not_entered; break; 392 case nca_s_op_rng_error: mst = rpc_s_op_rng_error; break; 393 case nca_s_who_are_you_failed: mst = rpc_s_who_are_you_failed; break; 394 case nca_s_proto_error: mst = rpc_s_protocol_error; break; 395 case nca_s_wrong_boot_time: mst = rpc_s_wrong_boot_time; break; 396 default: mst = rpc_s_unknown_reject; break; 397 } 398 399 rpc__dg_call_signal_failure(&ccall->c, mst); 400 401 return (RPC_C_DG_RDF_FREE_RQE); 402} 403 404/* 405 * R P C _ _ D G _ D O _ F A U L T 406 * 407 * Handle a call fault packet. 408 * 409 * Stash the fault pkt away for eventual retrieval by the client 410 * stub and signal a call "call_faulted" failure. 411 */ 412 413PRIVATE boolean rpc__dg_do_fault 414( 415 rpc_dg_sock_pool_elt_p_t sp, 416 rpc_dg_recvq_elt_p_t rqe, 417 rpc_dg_ccall_p_t ccall 418) 419{ 420 421 /* 422 * Perform common response packet processing. 423 */ 424 425 if (! rpc__dg_do_common_response(sp, rqe, ccall)) 426 return (RPC_C_DG_RDF_FREE_RQE); 427 428 RPC_DBG_GPRINTF(("(rpc__dg_do_fault) Got a live one [%s]\n", 429 rpc__dg_act_seq_string(rqe->hdrp))); 430 431 RPC_DG_CALL_LOCK_ASSERT(&ccall->c); 432 433 /* 434 * When in the orphan state, a fault is just as good as a quack. 435 */ 436 437 if (ccall->c.state == rpc_e_dg_cs_orphan) 438 { 439 ccall->quit.quack_rcvd = true; 440 rpc__dg_call_signal(&ccall->c); 441 return (RPC_C_DG_RDF_FREE_RQE); 442 } 443 444 /* 445 * A fault response terminates the OUTs data stream. 446 */ 447 448 ccall->c.rq.all_pkts_recvd = true; 449 450 ccall->fault_rqe = rqe; 451 rpc__dg_call_signal_failure(&ccall->c, rpc_s_call_faulted); 452 453 return (0 /* DON'T free the rqe */); 454} 455 456/* 457 * R P C _ _ D G _ D O _ R E S P O N S E 458 * 459 * Handle a response packet. 460 */ 461 462PRIVATE boolean rpc__dg_do_response 463( 464 rpc_dg_sock_pool_elt_p_t sp, 465 rpc_dg_recvq_elt_p_t rqe, 466 rpc_dg_ccall_p_t ccall 467) 468{ 469 boolean rqe_wake_thread; 470 rpc_dg_xmitq_p_t xq; 471 boolean32 drop; 472 473 /* 474 * Perform common response packet processing. 475 */ 476 477 if (! rpc__dg_do_common_response(sp, rqe, ccall)) 478 return (RPC_C_DG_RDF_FREE_RQE); 479 480 RPC_DG_CALL_LOCK_ASSERT(&ccall->c); 481 482 xq = &ccall->c.xq; 483 484 /* 485 * Free any packets we have on the transmit queue still since the 486 * response is (implicitly) ack'ing them. 487 */ 488 489 if (xq->head != NULL) 490 rpc__dg_xmitq_free(xq, &ccall->c); 491 492 /* 493 * If we were pinging the server, we can stop now. 494 */ 495 496 RPC_DG_PING_INFO_INIT(&ccall->ping); 497 498 /* 499 * Add the packet to the receive queue, noting whether or not it 500 * actually gets queued. 501 */ 502 503 drop = ! rpc__dg_call_recvq_insert(&ccall->c, rqe, &rqe_wake_thread); 504 505 /* 506 * If "recvq_insert" told us that there are a sufficient number of 507 * rqe's to warrant wakeing up the client then do so. 508 */ 509 510 if (rqe_wake_thread) 511 { 512 rpc__dg_call_signal(&ccall->c); 513 } 514 515 /* 516 * Decide on a return status. If the packet was dropped, tell the 517 * caller to free the packet. Otherwise, if we signalled the call 518 * that the packet was queued to, tell the listener thread to yield. 519 * Otherwise, return 0, meaning, don't free the packet, or yield. 520 */ 521 522 if (drop) 523 return (RPC_C_DG_RDF_FREE_RQE); 524 525 if (rqe_wake_thread) 526 return (RPC_C_DG_RDF_YIELD /* and DON'T free the rqe */); 527 528 return (0 /* DON'T free the rqe */); 529} 530 531/* 532 * P I N G _ L A T E R 533 * 534 * Schedule a ping to happen later for the specified ccall. This routine is 535 * shared by the "working" and "nocall/fack" packet processing routines. 536 */ 537 538INTERNAL void ping_later ( 539 rpc_dg_ccall_p_t /*ccall*/, 540 rpc_dg_recvq_elt_p_t /*rqe*/ 541 ); 542 543INTERNAL void ping_later 544( 545 rpc_dg_ccall_p_t ccall, 546 rpc_dg_recvq_elt_p_t rqe ATTRIBUTE_UNUSED 547) 548{ 549 struct rpc_dg_ping_info_t *ping; 550 rpc_clock_t now, duration, interval; 551 552 ping = &ccall->ping; 553 now = rpc__clock_stamp(); 554 555 /* 556 * Stop any ongoing pinging. 557 */ 558 559 ping->pinging = false; 560 561 /* 562 * Compute the time to start pinging again as a function of how long 563 * the call has been running. (The longer the call's been running, 564 * the longer we wait until starting to ping again.) 565 * 566 * Note that there's an interaction between the ping rate and the 567 * server's "max receive state idle time": the server, while in 568 * the receive state, may declare the client dead if it doesn't hear 569 * from it from it in a while. 570 */ 571 572 duration = now - ccall->c.start_time; 573 574 if (duration < RPC_CLOCK_SEC(10)) 575 interval = RPC_CLOCK_SEC(3); 576 else if (duration < RPC_CLOCK_SEC(30)) 577 interval = RPC_CLOCK_SEC(10); 578 else 579 interval = RPC_CLOCK_SEC(30); 580 581 ping->next_time = now + interval; 582 583 RPC_DBG_PRINTF(rpc_e_dbg_general, 3, 584 ("(stop_pinging) Next ping at: now = %lu, interval = %lu [%s]\n", 585 (unsigned long)now, (unsigned long)interval, 586 rpc__dg_act_seq_string(rqe->hdrp))); 587} 588 589/* 590 * R P C _ _ D G _ D O _ W O R K I N G 591 * 592 * Handle a working packet. Working's are received in response to pings 593 * and mean that the server has received all the in's. Note that the 594 * server may still fail the call (e.g., because it doesn't handle the 595 * requested interface). 596 */ 597 598PRIVATE boolean rpc__dg_do_working 599( 600 rpc_dg_sock_pool_elt_p_t sp, 601 rpc_dg_recvq_elt_p_t rqe, 602 rpc_dg_ccall_p_t ccall 603) 604{ 605 rpc_dg_xmitq_p_t xq; 606 607 RPC_LOCK_ASSERT(0); 608 609 /* 610 * Perform common response packet processing. 611 */ 612 613 if (! rpc__dg_do_common_response(sp, rqe, ccall)) 614 return (RPC_C_DG_RDF_FREE_RQE); 615 616 RPC_DG_CALL_LOCK_ASSERT(&ccall->c); 617 618 xq = &ccall->c.xq; 619 620 /* 621 * If our call is non-idempotent, free any packets we have on the 622 * transmit queue still since the working response is (implicitly) 623 * ack'ing the receipt of them. Note well that we MUST NOT free 624 * the queue for idempotent calls since the server is allowed to 625 * drop the response in which case a subsequent ping from us will 626 * induce a nocall response and oblige us to retransmit the request. 627 */ 628 629 if ((xq->base_flags & RPC_C_DG_PF_IDEMPOTENT) == 0 && 630 xq->head != NULL) 631 { 632 rpc__dg_xmitq_free(xq, &ccall->c); 633 } 634 635 ping_later(ccall, rqe); 636 637 return (RPC_C_DG_RDF_FREE_RQE); 638} 639 640/* 641 * R P C _ _ D G _ D O _ N O C A L L 642 * 643 * Handle a no-call packet. No-call's are received in response to pings. 644 * Note that in the case of large in's, some of which have already been 645 * fack'd, no-call simply means that not all the in's have arrived, NOT 646 * that the server knows nothing about the call. Confusing, eh? 647 */ 648 649PRIVATE boolean rpc__dg_do_nocall 650( 651 rpc_dg_sock_pool_elt_p_t sp, 652 rpc_dg_recvq_elt_p_t rqe, 653 rpc_dg_ccall_p_t ccall 654) 655{ 656 rpc_dg_xmitq_p_t xq; 657 658 RPC_LOCK_ASSERT(0); 659 660 /* 661 * Make sure the pkt is for the current call, that we are in the 662 * receive state, and that the call has not already failed. Note: 663 * the sequence number may be greater than our current one due to 664 * proxy calls. 665 */ 666 667 if (ccall == NULL 668 || RPC_DG_SEQ_IS_LT(rqe->hdrp->seq, ccall->c.call_seq) 669 || ccall->c.state != rpc_e_dg_cs_recv 670 || ccall->c.status != rpc_s_ok) 671 { 672 RPC_DBG_PRINTF(rpc_e_dbg_general, 2, 673 ("(rpc__dg_do_nocall) Dropped [%s]\n", 674 rpc__dg_act_seq_string(rqe->hdrp))); 675 return (RPC_C_DG_RDF_FREE_RQE); 676 } 677 678 RPC_DG_CALL_LOCK_ASSERT(&ccall->c); 679 680 if (! chk_sboot(rqe, ccall)) 681 { 682 return (RPC_C_DG_RDF_FREE_RQE); 683 } 684 685 xq = &ccall->c.xq; 686 687 /* 688 * When in the orphan state, a nocall is just as good as a quack. 689 */ 690 691 if (ccall->c.state == rpc_e_dg_cs_orphan) 692 { 693 ccall->quit.quack_rcvd = true; 694 rpc__dg_call_signal(&ccall->c); 695 return (RPC_C_DG_RDF_FREE_RQE); 696 } 697 698 if (xq->head == NULL) { 699 RPC_DBG_PRINTF(rpc_e_dbg_general, 2, 700 ("(rpc__dg_do_nocall) Transmit queue is empty [%s]\n", 701 rpc__dg_act_seq_string(rqe->hdrp))); 702 return (RPC_C_DG_RDF_FREE_RQE); 703 } 704 705 /* 706 * No-call means we should stop pinging. 707 */ 708 709 RPC_DG_PING_INFO_INIT(&ccall->ping); 710 711 /* 712 * If there's a body in this no-call, it must be a fack body. 713 */ 714 715 if (rqe->hdrp->len > 0) 716 { 717 boolean sent_data; 718 719 /* 720 * Process the nocall just like a fack. 721 */ 722 723 RPC_DBG_PRINTF(rpc_e_dbg_general, 3, 724 ("(rpc__dg_do_nocall) Has fack body [%s]\n", 725 rpc__dg_act_seq_string(rqe->hdrp))); 726 727 rpc__dg_fack_common(sp, rqe, &ccall->c, &sent_data); 728 729 /* 730 * Conditionally schedule the next ping for later (i.e., backed 731 * off, just as if we'd gotten a "working". The "condition" 732 * is that the fack processing has NOT just queued up some data 733 * to send. In this case, we must ping soon to verify that the 734 * frag was received. (The problem case comes when the call 735 * has been queued for long enough that the ping interval is 736 * longer than the comm timeout setting.) 737 */ 738 739 if (! sent_data) 740 { 741 ping_later(ccall, rqe); 742 } 743 744 return (RPC_C_DG_RDF_FREE_RQE); 745 } 746 747 /* 748 * =========== Process a no-call that lacks a fack body =========== 749 */ 750 751 /* 752 * If this is an idempotent call (which must mean a single pkt 753 * request, though we won't count on that) and we're retransmitting 754 * the beginning of a call, then it may have been the case that the 755 * call actually ran, but the response was lost. To ensure that 756 * we don't loose a cancel, reset some of our cancel state (which may 757 * result in re-forwarding a cancel) so that call_end() can make an 758 * accurate cancel_pending decision. 759 */ 760 761 if (xq->head->fragnum == 0 762 && (ccall->c.xq.base_flags & RPC_C_DG_PF_IDEMPOTENT)) 763 { 764 ccall->cancel.server_count = 0; 765 ccall->cancel.server_is_accepting = true; 766 ccall->cancel.server_had_pending = false; 767 /* Retain *current* ccall->cancel.local_count */ 768 } 769 770 /* 771 * Since we had begun pinging, we know that everything on the queue 772 * has been sent atleast once. However, the receipt of a nocall 773 * is an indication from the server that it's missing something. 774 * Unfortunately, we have no way of telling what it's missing, so 775 * all we can do is begin sending everything on the queue again. 776 */ 777 778 rpc__dg_xmitq_restart(&ccall->c); 779 780 RPC_DBG_PRINTF(rpc_e_dbg_general, 3, 781 ("(rpc__dg_do_nocall) Retransmitting %d frags [%s]\n", 782 xq->blast_size, rpc__dg_act_seq_string(rqe->hdrp))); 783 784 return (RPC_C_DG_RDF_FREE_RQE); 785} 786 787/* 788 * D O _ Q U A C K _ B O D Y 789 * 790 * Process the contents of a quack body. 791 * A quack with a body is interpreted as a cancel-request ack. 792 */ 793 794INTERNAL void do_quack_body 795( 796 rpc_dg_recvq_elt_p_t rqe, 797 rpc_dg_ccall_p_t ccall 798) 799{ 800 unsigned32 cancel_id; 801 boolean server_is_accepting; 802 803#ifndef MISPACKED_HDR 804 805 rpc_dg_quackpkt_body_p_t bodyp = (rpc_dg_quackpkt_body_p_t) &rqe->pkt->body; 806 807 /* 808 * Make sure we understand the quack packet body version. 809 */ 810 811 if (bodyp->vers != RPC_C_DG_QUACKPKT_BODY_VERS) 812 { 813 RPC_DBG_GPRINTF(("(do_quack_body) Unknown version; Dropped [%s]\n", 814 rpc__dg_act_seq_string(rqe->hdrp))); 815 return; 816 } 817 818 /* 819 * Extract the cancel_id of the cancel being ack'ed and the sender's 820 * server_is_accepting (cancels) flag. 821 */ 822 823 cancel_id = bodyp->cancel_id; 824 server_is_accepting = bodyp->server_is_accepting; 825 826 if (NDR_DREP_INT_REP(rqe->hdrp->drep) != ndr_g_local_drep.int_rep) 827 { 828 SWAB_INPLACE_32(cancel_id); 829 } 830#else 831 832#error "No code for mispacked_hdr here!" 833 834#endif /* MISPACKED_HDR */ 835 836 /* 837 * Update the call handle information. Since pkts may be duplicated 838 * / rcvd out of order... ignore "old" cancel quacks. 839 * 840 * While we currently don't think that a server will ever tell us 841 * to re-enable acceptance once it declares that it is no longer 842 * accepting cancels there's no good reason to enforce this (and 843 * there's good reason to leave the flexibility in). Of course, 844 * we don't want "old" acks to affect the state. 845 * 846 * Define the architectural requirement that servers may adjust their 847 * cancel acceptance state as they see fit; however, the clients 848 * will not adapt to the new state unless the state is conveyed to 849 * the client in a cancel quack specifying a cancel_id that 850 * at least as high as the highest cancel previously acked by the 851 * server. 852 */ 853 if (cancel_id < ccall->cancel.server_count) 854 { 855 RPC_DBG_PRINTF(rpc_e_dbg_recv, 1, 856 ("(do_quack_body) Old quack; Dropped [%s]\n", 857 rpc__dg_act_seq_string(rqe->hdrp))); 858 return; 859 } 860 861 ccall->cancel.server_count = cancel_id; 862 ccall->cancel.server_is_accepting = server_is_accepting; 863} 864 865/* 866 * R P C _ _ D G _ D O _ Q U A C K 867 * 868 * Handle a call quit acknowlegement packet. 869 * Quacks have two forms: 870 * a) orphan-request ack (2.0 and pre 2.0) 871 * b) cancel-request ack (2.0 only) 872 * 873 * Note: A 2.0 client sending a cancel-request will get a orphan-request-ack 874 * when talking to a 1.5.1 server (since cancel and orphan requests are 875 * identical from the 1.5.1 server's perspective). 876 */ 877 878PRIVATE boolean rpc__dg_do_quack 879( 880 rpc_dg_sock_pool_elt_p_t sp, 881 rpc_dg_recvq_elt_p_t rqe, 882 rpc_dg_ccall_p_t ccall 883) 884{ 885 /* 886 * Perform common response packet processing. 887 */ 888 889 if (! rpc__dg_do_common_response(sp, rqe, ccall)) 890 return (RPC_C_DG_RDF_FREE_RQE); 891 892 RPC_DBG_PRINTF(rpc_e_dbg_general, 3, 893 ("(rpc__dg_do_quack) Rcvd %s quack [%s]\n", 894 rqe->hdrp->len != 0 ? "cancel" : "orphan", 895 rpc__dg_act_seq_string(rqe->hdrp))); 896 897 RPC_DG_CALL_LOCK_ASSERT(&ccall->c); 898 899 /* 900 * An orphan-quack is identified by a quack without a body 901 * (a cancel-quack has a body). 902 */ 903 if (rqe->hdrp->len != 0) 904 { 905 do_quack_body(rqe, ccall); 906 } 907 else 908 { 909 /* 910 * If we're not in the orphan state (this orphan-quack IS for our call) 911 * we must be talking to a 1.5.1 server (which has now orphaned 912 * the call, so there's no need to continue). 913 */ 914 915 if (ccall->c.state != rpc_e_dg_cs_orphan) 916 { 917 RPC_DBG_GPRINTF( 918 ("(rpc__dg_do_quack) Rcvd orphan quack in response to cancel %s [%s]\n", 919 rpc__dg_call_state_name(ccall->c.state), 920 rpc__dg_act_seq_string(rqe->hdrp))); 921 rpc__dg_call_signal_failure(&ccall->c, rpc_s_call_cancelled); 922 return (RPC_C_DG_RDF_FREE_RQE); 923 } 924 925 /* 926 * A "quack" packet has been received, signal the thread waiting in 927 * rpc__dg_call_end() to clean up the resources held by the call and 928 * transition to the idle state. 929 */ 930 931 ccall->quit.quack_rcvd = true; 932 rpc__dg_call_signal(&ccall->c); 933 } 934 935 return (RPC_C_DG_RDF_FREE_RQE); 936} 937