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** cnsclsm.c 82** 83** FACILITY: 84** 85** Remote Procedure Call (RPC) 86** 87** ABSTRACT: 88** 89** Server call State Machine for the Connection-based RPC runtime. 90** 91** 92*/ 93 94 95#include <commonp.h> /* Common declarations for all RPC runtime */ 96#include <com.h> /* Common communications services */ 97#include <comprot.h> /* Common protocol services */ 98#include <ndrglob.h> /* NDR representation global declarations */ 99#include <ndrp.h> /* System dependent NDR decls */ 100#include <cnp.h> /* NCA Connection private declarations */ 101#include <cnfbuf.h> /* NCA Connection fragment buffer declarations */ 102#include <cnpkt.h> /* NCA Connection protocol header */ 103#include <cnsm.h> /* NCA Connection state machine declarations */ 104#include <cnxfer.h> /* NCA Connection buffered data transfer */ 105#include <cnassoc.h> /* NCA Connection association services */ 106#include <comcthd.h> /* Externals for Call Thread sub-component */ 107#include <cncall.h> /* NCA connection call service */ 108#include <cnclsm.h> 109 110#include <dce/rpcexc.h> 111 112/******************************************************************************/ 113/* 114 * Global Definitions 115 */ 116#ifdef DEBUG 117GLOBAL const char *rpc_g_cn_call_server_events [] = 118{ 119 "RESPONSE ", 120 "INDICATION ", 121 "FAULT_DNE ", 122 "FAULT ", 123 "LOCAL_ALERT ", 124 "END ", 125 "REMOTE_ALERT_IND ", 126 "ORPHANED " 127}; 128 129GLOBAL const char *rpc_g_cn_call_server_states [] = 130{ 131 "INIT ", 132 "REQUEST ", 133 "RESPONSE ", 134 "CALL_COMPLETED " 135}; 136#endif 137 138 139/***********************************************************************/ 140/* 141 * S E R V E R C A L L P R E D I C A T E T A B L E 142 */ 143 144/* 145 * The predicates. 146 * As a performance enhancement, we have changed some predicate routines 147 * and made them macros and we have absorbed the predicates into the 148 * actions. Thus, there is no longer a need for the predicate table. 149 * We invoke the predicate functions as MACROS or as function calls 150 * from within the action routines. 151 */ 152/* 153 * The predicate routine prototypes. 154 */ 155INTERNAL unsigned8 disconnected_maybe_pred_rtn 156 ( 157 dce_pointer_t spc_struct, 158 dce_pointer_t event_param 159 ) ATTRIBUTE_UNUSED; 160INTERNAL unsigned8 request_fault_pred_rtn 161 ( 162 dce_pointer_t spc_struct, 163 dce_pointer_t event_param 164 ) ATTRIBUTE_UNUSED; 165INTERNAL unsigned8 response_fault_pred_rtn 166 ( 167 dce_pointer_t spc_struct, 168 dce_pointer_t event_param 169 ) ATTRIBUTE_UNUSED; 170INTERNAL unsigned8 last_recv_frag_pred_rtn 171 ( 172 dce_pointer_t spc_struct, 173 dce_pointer_t event_param 174 ) ATTRIBUTE_UNUSED; 175INTERNAL unsigned8 first_frag_pred_rtn 176 ( 177 dce_pointer_t spc_struct, 178 dce_pointer_t event_param 179 ) ATTRIBUTE_UNUSED; 180INTERNAL unsigned8 disc_last_send_pred_rtn 181 ( 182 dce_pointer_t spc_struct, 183 dce_pointer_t event_param 184 ) ATTRIBUTE_UNUSED; 185 186 187/***********************************************************************/ 188/* 189 * S E R V E R C A L L A C T I O N T A B L E 190 */ 191 192/***********************************************************************/ 193 194/* 195 * The actions. 196 */ 197#define HANDLE_FIRST_FRAG 0 198#define HANDLE_FRAG 1 199#define SEND_CALL_RESP 2 200#define SEND_CALL_FAULT 3 201#define PROCESS_ALERT_MSG 4 202#define ABORT_RESP 5 203#define ABORT_RESP_SEND_FAULT 6 204#define STOP_ORPHAN 7 205#define DISCARD_FRAGMENT 8 206#define CALL_END 9 207#define PROTOCOL_ERROR 10 208 209/* 210 * We do not currently execute actions when we abort a receive. 211 */ 212#define ABORT_RECEIVE RPC_C_SM_NO_ACTION 213#define ABORT_RECEIVE_SEND_FAULT SEND_CALL_FAULT 214 215/* 216 * The action routine prototypes. 217 */ 218INTERNAL unsigned32 handle_first_frag_action_rtn ( 219 dce_pointer_t /*spc_struct*/, 220 dce_pointer_t /*event_param*/, 221 dce_pointer_t /*sm*/ 222 ); 223INTERNAL unsigned32 handle_frag_action_rtn ( 224 dce_pointer_t /*spc_struct*/, 225 dce_pointer_t /*event_param*/, 226 dce_pointer_t /*sm*/ 227 ); 228INTERNAL unsigned32 send_call_resp_action_rtn ( 229 dce_pointer_t /*spc_struct*/, 230 dce_pointer_t /*event_param*/, 231 dce_pointer_t /*sm*/ 232 ); 233INTERNAL unsigned32 send_call_fault_action_rtn ( 234 dce_pointer_t /*spc_struct*/, 235 dce_pointer_t /*event_param*/, 236 dce_pointer_t /*sm*/ 237 ); 238INTERNAL unsigned32 process_alert_msg_action_rtn ( 239 dce_pointer_t /*spc_struct*/, 240 dce_pointer_t /*event_param*/, 241 dce_pointer_t /*sm*/ 242 ); 243 244INTERNAL unsigned32 abort_resp_action_rtn ( 245 dce_pointer_t /*spc_struct*/, 246 dce_pointer_t /*event_param*/, 247 dce_pointer_t /*sm*/ 248 ); 249 250INTERNAL unsigned32 abort_resp_send_fault_action_rtn ( 251 dce_pointer_t /*spc_struct*/, 252 dce_pointer_t /*event_param*/, 253 dce_pointer_t /*sm*/ 254 ); 255INTERNAL unsigned32 stop_orphan_action_rtn ( 256 dce_pointer_t /*spc_struct*/, 257 dce_pointer_t /*event_param*/, 258 dce_pointer_t /*sm*/ 259 ); 260INTERNAL unsigned32 discard_fragment_action_rtn ( 261 dce_pointer_t /*spc_struct*/, 262 dce_pointer_t /*event_param*/, 263 dce_pointer_t /*sm*/ 264 ); 265INTERNAL unsigned32 call_end_action_rtn ( 266 dce_pointer_t /*spc_struct*/, 267 dce_pointer_t /*event_param*/, 268 dce_pointer_t /*sm*/ 269 ); 270 271/* 272 * The action table itself. 273 */ 274GLOBAL rpc_cn_sm_action_fn_t rpc_g_cn_server_call_action_tbl [] = 275{ 276 handle_first_frag_action_rtn, 277 handle_frag_action_rtn, 278 send_call_resp_action_rtn, 279 send_call_fault_action_rtn, 280 process_alert_msg_action_rtn, 281 abort_resp_action_rtn, 282 abort_resp_send_fault_action_rtn, 283 stop_orphan_action_rtn, 284 discard_fragment_action_rtn, 285 call_end_action_rtn, 286 rpc__cn_call_sm_protocol_error 287}; 288 289/***********************************************************************/ 290/* 291 * S E R V E R C A L L S T A T E T A B L E 292 */ 293 294/* 295 * A state table entry exists for every state in the state machine. 296 * In the case of the server call state machine, for example, a 297 * state table entry exists for init, call_request, call_response, 298 * etc. 299 * 300 * Each state table entry describes the actions and state transitions 301 * which can occur in response to each event while in that state. 302 * So for example, the state table entry for the init state must 303 * describe the outcomes for every event. 304 * 305 * The outcome for an event is a new state and an action routine to 306 * invoke. 307 * 308 * Sometimes, how a given event is handled depends upon certain 309 * conditions. For example, a fault_dne event occurring in the 310 * call_response state is handled differently depending upon whether 311 * the connection has been disconnected and the semantics of the 312 * call. This is translated into a number of different outcomes 313 * for each event. 314 * 315 * As an optimization, the structure rpc_cn_sm_state_tbl_entry_t 316 * was modified to contain one unsigned8 value. That value can 317 * be either a state to transition to, or the action index. 318 * We distinguish between states and action indexes by value; 319 * state values are >=100 and action indexes are in the range 320 * of 1 - 14. If the state and event combination in the state table 321 * requires an action, then the rpc_cn_sm_state_tbl_entry_t structure 322 * contains an index into the action tbl for that set of 323 * circumstances. The action routine itself will contain a 324 * predicate function, usually inline, and the action routine will 325 * update the control block's cur_state which in effect, is the 326 * next state. The predicate function within the action routine 327 * will guide the logic through the action so that the appropriate 328 * action is taken depending on the outcome of the predicate 329 * function. If the state and event combination requires no action but does 330 * require a state update, then we look to rpc_cn_sm_state_tbl_entry_t 331 * to contain that state update value. 332 * 333 */ 334 335INTERNAL rpc_cn_sm_state_tbl_entry_t init_state = 336 337 { 338 ILLEGAL_TRANSITION, /* event 0 - rpc_resp */ 339 {HANDLE_FIRST_FRAG}, /* event 1 - rpc_ind */ 340 ILLEGAL_TRANSITION, /* event 2 - fault_dne */ 341 ILLEGAL_TRANSITION, /* event 3 - fault */ 342 ILLEGAL_TRANSITION, /* event 4 - local_alert */ 343 {RPC_C_SERVER_CALL_CALL_COMPLETED}, /* event 5 - call_end state */ 344 ILLEGAL_TRANSITION, /* event 6 - remote_alert_ind */ 345 ILLEGAL_TRANSITION /* event 7 - orphaned */ 346 }; 347 348INTERNAL rpc_cn_sm_state_tbl_entry_t call_request_state = 349 { 350 ILLEGAL_TRANSITION, /* event 0 - rpc_resp */ 351 {HANDLE_FRAG}, /* event 1 - rpc_ind */ 352 {ABORT_RECEIVE_SEND_FAULT}, /* event 2 - fault_dne */ 353 {ABORT_RECEIVE_SEND_FAULT}, /* event 3 - fault */ 354 ILLEGAL_TRANSITION, /* event 4 - local_alert */ 355 {CALL_END}, /* event 5 - call_end */ 356 {PROCESS_ALERT_MSG}, /* event 6 - remote_alert_ind */ 357 /* 358 * This transition should not be going to the call 359 * completed state when the call is still executing. 360 * However, this implementation will return an error to any 361 * attempts to send a reponse on a call which is in the 362 * call_completed state before entering the state machine. 363 */ 364 {STOP_ORPHAN} /* event 7 - orphaned */ 365 }; 366 367INTERNAL rpc_cn_sm_state_tbl_entry_t call_response_state = 368 { 369 {SEND_CALL_RESP}, /* event 0 - rpc_resp */ 370 ILLEGAL_TRANSITION, /* event 1 - rpc_ind */ 371 {ABORT_RESP_SEND_FAULT}, /* event 2 - fault_dne */ 372 {ABORT_RESP_SEND_FAULT}, /* event 3 - fault */ 373 ILLEGAL_TRANSITION, /* event 4 - local_alert */ 374 {CALL_END}, /* event 5 - call_end */ 375 {PROCESS_ALERT_MSG}, /* event 6 - remote_alert_ind */ 376 {STOP_ORPHAN} /* event 7 - orphaned */ 377 }; 378 379 380INTERNAL rpc_cn_sm_state_tbl_entry_t call_completed_state = 381 { 382 ILLEGAL_TRANSITION, /* event 0 */ 383 ILLEGAL_TRANSITION, /* event 1 */ 384 ILLEGAL_TRANSITION, /* event 2 */ 385 ILLEGAL_TRANSITION, /* event 3 */ 386 ILLEGAL_TRANSITION, /* event 4 */ 387 {RPC_C_SERVER_CALL_CALL_COMPLETED}, /* event 5 - call_end */ 388 ILLEGAL_TRANSITION, /* event 6 */ 389 {RPC_C_SERVER_CALL_CALL_COMPLETED} /* event 7 - orphaned */ 390 }; 391 392GLOBAL rpc_cn_sm_state_entry_p_t rpc_g_cn_server_call_sm [] = 393{ 394 init_state, /* state 0 - init */ 395 call_request_state, /* state 1 - call_request */ 396 call_response_state, /* state 2 - call_response */ 397 call_completed_state /* state 3 - call_completed */ 398}; 399 400 401/***********************************************************************/ 402/* 403 * 404 * S E R V E R C A L L P R E D I C A T E R O U T I N E S 405 * 406 */ 407 408/***********************************************************************/ 409 410/* 411**++ 412** 413** ROUTINE NAME: disconnected_maybe_pred_rtn 414** 415** SCOPE: INTERNAL 416** 417** DESCRIPTION: 418** 419** Predicate routine to evaluate whether the communications link 420** has been disconnected or if the call has maybe semantics. 421** This routine is invoked from the Call Request and Call Response 422** states when an RPCInd or RPCResp event occurred. 423** 424** INPUTS: 425** 426** spc_struct The call rep. Note that this is passed in as 427** the special structure which is passed to the 428** state machine event evaluation routine. 429** 430** event_param Fragment buffer containing the received data. 431** Note that it is passed in as the special event 432** related parameter which is passed to the state 433** machine event evaluation routine. 434** 435** INPUTS/OUTPUTS: none 436** 437** OUTPUTS: none 438** 439** IMPLICIT INPUTS: the association status has been set to non-OK if the 440** connection has been disconnected. 441** 442** IMPLICIT OUTPUTS: none 443** 444** FUNCTION VALUE: 0 if Disconnected and MaybeSemantics are both false 445** 1 if either Disconnected or MaybeSemantics is true 446** 447** SIDE EFFECTS: none 448** 449**-- 450**/ 451 452INTERNAL unsigned8 disconnected_maybe_pred_rtn 453( 454 dce_pointer_t spc_struct, 455 dce_pointer_t event_param 456) 457{ 458 RPC_CN_DBG_RTN_PRINTF(SERVER disconnected_maybe_pred_rtn); 459 460 if ( (((rpc_cn_call_rep_p_t) spc_struct)->assoc->assoc_status != 461 rpc_s_ok) || 462 (RPC_CN_PKT_FLAGS (RPC_CN_FRAGBUF_PKT_HDR (event_param)) & 463 RPC_C_CN_FLAGS_MAYBE) ) 464 { 465 return (1); 466 } 467 else 468 { 469 return (0); 470 } 471} 472 473 474/* 475**++ 476** 477** ROUTINE NAME: disc_last_send_pred_rtn 478** 479** SCOPE: INTERNAL 480** 481** DESCRIPTION: 482** 483** Predicate routine which evaluates whether the communications link 484** has been disconnected and whether this the the last fragment 485** of the response. It is invoked from the Call Response state when 486** an RPCResp event occurred. 487** 488** INPUTS: 489** 490** spc_struct The call rep. Note that this is passed in as 491** the special structure which is passed to the 492** state machine event evaluation routine. 493** 494** event_param Iovector element containing the stub data for 495** the response. 496** Note that it is passed in as the special event 497** related parameter which is passed to the state 498** machine event evaluation routine. 499** 500** INPUTS/OUTPUTS: none 501** 502** OUTPUTS: none 503** 504** IMPLICIT INPUTS: the association status has been set to non-OK if the 505** connection has been disconnected. 506** 507** IMPLICIT OUTPUTS: none 508** 509** FUNCTION VALUE: 0 if Disconnected is true 510** 1 if Disconnected is false and this is the 511** last fragment of the response. 512** (NOTE that this value cannot in fact be 513** returned since we can only detect 514** the last fragment when the CALL_END 515** is issued.) 516** 2 if Disconnected is false and this is not 517** the last fragment of the response. 518** 519** SIDE EFFECTS: none 520** 521**-- 522**/ 523 524INTERNAL unsigned8 disc_last_send_pred_rtn 525( 526 dce_pointer_t spc_struct, 527 dce_pointer_t event_param ATTRIBUTE_UNUSED 528) 529{ 530 RPC_CN_DBG_RTN_PRINTF(SERVER disc_last_send_pred_rtn); 531 532 if (((rpc_cn_call_rep_p_t) spc_struct)->assoc->assoc_status != 533 rpc_s_ok) 534 { 535 return (0); 536 } 537 else 538 { 539 return (2); 540 } 541 542 /* 543 * Note, our current implementation can never detect the 544 * last fragment of the response until the CALL_END is 545 * issued. Consequently, 1 cannot be returned. 546 */ 547} 548 549 550/* 551**++ 552** 553** MACRO NAME: DISC_LAST_SEND_PRED 554** 555** SCOPE: INTERNAL 556** 557** DESCRIPTION: 558** 559** This is a macro version of the disc_last_send_pred_rtn() predicate. 560** We added the macro version to avoid overhead when calling the 561** predicate function from within the action routines. 562** Predicate macro which evaluates whether the communications link 563** has been disconnected and whether this the the last fragment 564** of the response. It is invoked from the Call Response state when 565** an RPCResp event occurred. 566** 567** INPUTS: 568** 569** spc_struct The call rep. Note that this is passed in as 570** the special structure which is passed to the 571** state machine event evaluation routine. 572** 573** event_param Iovector element containing the stub data for 574** the response. 575** Note that it is passed in as the special event 576** related parameter which is passed to the state 577** machine event evaluation routine. 578** 579** status Instead of returning a value from the macro, 580** write the value calculated in the macro to 581** status. Status' scope includes the routine 582** calling the macro. Check status in the calling 583** routine to determine next state and in cases, 584** flow through the action routine. 585** 586** INPUTS/OUTPUTS: none 587** 588** OUTPUTS: 589** 590** status See explanation above. 591** 592** IMPLICIT INPUTS: none 593** 594** IMPLICIT OUTPUTS: none 595** 596** FUNCTION VALUE: 0 if Disconnected is true 597** 1 if Disconnected is false and this is the 598** last fragment of the response. 599** (NOTE that this value cannot in fact be 600** returned since we can only detect 601** the last fragment when the call_end 602** is issued.) 603** 2 if Disconnected is false and this is not 604** the last fragment of the response. 605** 606** SIDE EFFECTS: none 607** 608**-- 609**/ 610#define DISC_LAST_SEND_PRED(spc_struct, event_param, status) \ 611{ \ 612 RPC_CN_DBG_RTN_PRINTF(SERVER disc_last_send_pred_macro); \ 613 if (((rpc_cn_call_rep_p_t) spc_struct)->assoc->assoc_status != rpc_s_ok) \ 614 { \ 615 status = 0; \ 616 } \ 617 else \ 618 { \ 619 status = 2; \ 620 } \ 621} 622 623 624/* 625**++ 626** 627** ROUTINE NAME: request_fault_pred_rtn 628** 629** SCOPE: INTERNAL 630** 631** DESCRIPTION: 632** 633** Routine evaluating the combination of the predicates: MaybeSemantics, 634** Disconnected, and LastSendFrag for the fault. It is invoked from 635** the Call Request state when either a fault or fault_dne event occurs. 636** 637** INPUTS: 638** 639** spc_struct The call rep. Note that this is passed in as 640** the special structure which is passed to the 641** state machine event evaluation routine. 642** 643** event_param Iovector element containing the fault data. 644** Note that it is passed in as the special event 645** related parameter which is passed to the state 646** machine event evaluation routine. 647** This argument is ignored in the current 648** implementation. 649** 650** INPUTS/OUTPUTS: none 651** 652** OUTPUTS: none 653** 654** IMPLICIT INPUTS: the association status has been set to non-OK if the 655** connection has been disconnected. 656** 657** IMPLICIT OUTPUTS: none 658** 659** FUNCTION VALUE: 0 if MaybeSemantics or Disconnected is true 660** 1 if LastSendFrag for the fault is true and 661** and both MaybeSemantics and Disconnected 662** are false 663** 2 if LastSendFrag for the fault is false, 664** and both MaybeSemantics and Disconnected 665** are false. 666** Note that in our current implementation, 667** this outcome cannot occur. 668** 669** SIDE EFFECTS: none 670** 671**-- 672**/ 673 674INTERNAL unsigned8 request_fault_pred_rtn 675( 676 dce_pointer_t spc_struct, 677 dce_pointer_t event_param ATTRIBUTE_UNUSED 678) 679{ 680 rpc_cn_call_rep_p_t call_rep; 681 682 RPC_CN_DBG_RTN_PRINTF(SERVER request_fault_pred_rtn); 683 684 call_rep = (rpc_cn_call_rep_p_t) spc_struct; 685 686 if ( ( call_rep->assoc->assoc_status != 687 rpc_s_ok ) || 688 ( (RPC_CN_PKT_FLAGS ( (rpc_cn_packet_p_t) RPC_CN_CREP_SEND_HDR (call_rep))) 689 & RPC_C_CN_FLAGS_MAYBE ) ) 690 { 691 return (0); 692 } 693 else 694 { 695 /* 696 * Note: Although the architecture allows the fault data 697 * to be sent in several chunks, the current implementation 698 * assumes that it is passed to the runtime in a single 699 * operation. 700 */ 701 return (1); 702 } 703} 704 705 706/* 707**++ 708** 709** MACRO NAME: REQUEST_FAULT_PRED 710** 711** SCOPE: INTERNAL 712** 713** DESCRIPTION: 714** 715** This is a macro version of the request_fault_pred_rtn() predicate. 716** We added the macro version to avoid overhead when calling the 717** predicate function from within the action routines. 718** Macro evaluating the combination of the predicates: MaybeSemantics, 719** Disconnected, and LastSendFrag for the fault. It is invoked from 720** the Call Request state when either a fault or fault_dne event occurs. 721** 722** INPUTS: 723** 724** spc_struct The call rep. Note that this is passed in as 725** the special structure which is passed to the 726** state machine event evaluation routine. 727** 728** event_param Iovector element containing the fault data. 729** Note that it is passed in as the special event 730** related parameter which is passed to the state 731** machine event evaluation routine. 732** This argument is ignored in the current 733** implementation. 734** 735** status Instead of returning a value from the macro, 736** write the value calculated in the macro to 737** status. Status' scope includes the routine 738** calling the macro. Check status in the calling 739** routine to determine next state and in cases, 740** flow through the action routine. 741** 742** INPUTS/OUTPUTS: none 743** 744** OUTPUTS: 745** 746** status See explanation above. 747** 748** IMPLICIT INPUTS: none 749** 750** IMPLICIT OUTPUTS: none 751** 752** FUNCTION VALUE: 0 if MaybeSemantics or Disconnected is true 753** 1 if LastSendFrag for the fault is true and 754** and both MaybeSemantics and Disconnected 755** are false 756** 2 if LastSendFrag for the fault is false, 757** and both MaybeSemantics and Disconnected 758** are false. 759** Note that in our current implementation, 760** this outcome cannot occur. 761** 762** SIDE EFFECTS: none 763** 764**-- 765**/ 766#define REQUEST_FAULT_PRED(call_rep, event_param, status) \ 767{ \ 768 RPC_CN_DBG_RTN_PRINTF(SERVER request_fault_pred_macro); \ 769 if ( ( call_rep->assoc->assoc_status != \ 770 rpc_s_ok ) || \ 771 ( (RPC_CN_PKT_FLAGS ( (rpc_cn_packet_p_t) RPC_CN_CREP_SEND_HDR (call_rep))) \ 772 & RPC_C_CN_FLAGS_MAYBE ) ) \ 773 { \ 774 status = 0; \ 775 } \ 776 else \ 777 { \ 778 status = 1; \ 779 } \ 780} 781 782 783/* 784**++ 785** 786** ROUTINE NAME: response_fault_pred_rtn 787** 788** SCOPE: INTERNAL 789** 790** DESCRIPTION: 791** 792** Evaluate the MaybeSemantics and Disconnected predicates from 793** the Call Response state when either a fault or fault_dne 794** event occurs. 795** 796** INPUTS: 797** 798** spc_struct The call rep. Note that this is passed in as 799** the special structure which is passed to the 800** state machine event evaluation routine. 801** 802** event_param The special event related parameter which is 803** passed to the state machine event evaluation 804** routine. 805** This input argument is ignored. 806** 807** INPUTS/OUTPUTS: none 808** 809** OUTPUTS: none 810** 811** IMPLICIT INPUTS: the association status has been set to non-OK if the 812** connection has been disconnected. 813** 814** IMPLICIT OUTPUTS: none 815** 816** FUNCTION VALUE: 0 if MaybeSemantics true, 817** 1 if Disconnected is true, 818** 2 otherwise. 819** 820** NOTE that the architecture allows 4 possible return values 821** so that fault data can be transmitted in several 822** operations. The current implementation assumes that 823** any fault data is transmitted in a single operation. 824** 825** SIDE EFFECTS: none 826** 827**-- 828**/ 829 830INTERNAL unsigned8 response_fault_pred_rtn 831( 832 dce_pointer_t spc_struct, 833 dce_pointer_t event_param ATTRIBUTE_UNUSED 834) 835{ 836 rpc_cn_packet_p_t header_p; 837 838 RPC_CN_DBG_RTN_PRINTF(SERVER response_fault_pred_rtn); 839 840 header_p = (rpc_cn_packet_p_t) RPC_CN_CREP_SEND_HDR ( 841 (rpc_cn_call_rep_p_t) spc_struct); 842 843 if (RPC_CN_PKT_FLAGS (header_p) & RPC_C_CN_FLAGS_MAYBE) 844 { 845 return (0); 846 } 847 else 848 { 849 if (((rpc_cn_call_rep_p_t) spc_struct)->assoc->assoc_status 850 != rpc_s_ok) 851 { 852 return (1); 853 } 854 else 855 { 856 return (2); 857 } 858 } 859} 860 861 862/* 863**++ 864** 865** MACRO NAME: RESPONSE_FAULT_PRED 866** 867** SCOPE: INTERNAL 868** 869** DESCRIPTION: 870** 871** This is a macro version of the response_fault_pred_rtn() predicate. 872** We added the macro version to avoid overhead when calling the 873** predicate function from within the action routines. 874** Evaluate the MaybeSemantics and Disconnected predicates from 875** the Call Response state when either a fault or fault_dne 876** event occurs. 877** 878** INPUTS: 879** 880** spc_struct The call rep. Note that this is passed in as 881** the special structure which is passed to the 882** state machine event evaluation routine. 883** 884** event_param The special event related parameter which is 885** passed to the state machine event evaluation 886** routine. 887** This input argument is ignored. 888** 889** status Instead of returning a value from the macro, 890** write the value calculated in the macro to 891** status. Status' scope includes the routine 892** calling the macro. Check status in the calling 893** routine to determine next state and in cases, 894** flow through the action routine. 895** 896** INPUTS/OUTPUTS: none 897** 898** OUTPUTS: 899** 900** status See explanation above. 901** 902** IMPLICIT INPUTS: none 903** 904** IMPLICIT OUTPUTS: none 905** 906** FUNCTION VALUE: 0 if MaybeSemantics true, 907** 1 if Disconnected is true, 908** 2 otherwise. 909** 910** NOTE that the architecture allows 4 possible return values 911** so that fault data can be transmitted in several 912** operations. The current implementation assumes that 913** any fault data is transmitted in a single operation. 914** 915** SIDE EFFECTS: none 916** 917**-- 918**/ 919#define RESPONSE_FAULT_PRED(spc_struct, event_param, status) \ 920{ \ 921 RPC_CN_DBG_RTN_PRINTF(SERVER response_fault_pred_macro); \ 922 header_p = (rpc_cn_packet_p_t) RPC_CN_CREP_SEND_HDR ( \ 923 (rpc_cn_call_rep_p_t) spc_struct); \ 924 if (RPC_CN_PKT_FLAGS (header_p) & RPC_C_CN_FLAGS_MAYBE) \ 925 { \ 926 status = 0; \ 927 } \ 928 else \ 929 { \ 930 if (((rpc_cn_call_rep_p_t) spc_struct)->assoc->assoc_status != rpc_s_ok) \ 931 { \ 932 status = 1; \ 933 } \ 934 else \ 935 { \ 936 status = 2; \ 937 } \ 938 } \ 939} 940 941 942/* 943**++ 944** 945** ROUTINE NAME: last_recv_frag_pred_rtn 946** 947** SCOPE: INTERNAL 948** 949** DESCRIPTION: 950** 951** Evaluate whether this is the last received request fragment 952** when an RPCInd event occurs. 953** 954** INPUTS: 955** 956** spc_struct This argument is the special structure which 957** is passed to the state machine event evaluation 958** routine. 959** This argument is ignored. 960** 961** event_param The received packet contained in a fragment 962** buffer. This is passed in as the special 963** event related parameter by the state machine 964** event evaluation routine. 965** 966** INPUTS/OUTPUTS: none 967** 968** OUTPUTS: none 969** 970** IMPLICIT INPUTS: none 971** 972** IMPLICIT OUTPUTS: none 973** 974** FUNCTION VALUE: 0 if LastRecvFrag is false 975** 1 if LastRecvFrag is true 976** 977** SIDE EFFECTS: none 978** 979**-- 980**/ 981 982INTERNAL unsigned8 last_recv_frag_pred_rtn 983( 984 dce_pointer_t spc_struct ATTRIBUTE_UNUSED, 985 dce_pointer_t event_param 986) 987{ 988 989 RPC_CN_DBG_RTN_PRINTF(SERVER last_recv_frag_pred_rtn); 990 991 if (RPC_CN_PKT_FLAGS (RPC_CN_FRAGBUF_PKT_HDR (event_param)) & 992 RPC_C_CN_FLAGS_LAST_FRAG) 993 { 994 return (1); 995 } 996 else 997 { 998 return (0); 999 } 1000} 1001 1002 1003/* 1004**++ 1005** 1006** MACRO NAME: LAST_RECV_FRAG_PRED 1007** 1008** SCOPE: INTERNAL 1009** 1010** DESCRIPTION: 1011** 1012** This is a macro of the last_recv_frag_pred_rtn routine 1013** introduced to avoid the overhead of a call-to-subroutine. 1014** Evaluate whether this is the last received request fragment 1015** when an RPCInd event occurs. 1016** 1017** INPUTS: 1018** 1019** spc_struct The association group. Note that this is passed in as 1020** the special structure which is passed to the 1021** state machine event evaluation routine. 1022** 1023** event_param The special event related parameter which is 1024** passed to the state machine event evaluation 1025** routine. 1026** This input argument is ignored. 1027** 1028** status Instead of returning a value from the macro, 1029** write the value calculated in the macro to 1030** status. Status' scope includes the routine 1031** calling the macro. Check status in the calling 1032** routine to determine next state and in cases, 1033** flow through the action routine. 1034** 1035** INPUTS/OUTPUTS: none 1036** 1037** OUTPUTS: 1038** 1039** status See explanation above. 1040** 1041** IMPLICIT INPUTS: none 1042** 1043** IMPLICIT OUTPUTS: none 1044** 1045** FUNCTION VALUE: 0 if LastRecvFrag is false 1046** 1 if LastRecvFrag is true 1047** 1048** SIDE EFFECTS: none 1049** 1050**-- 1051**/ 1052#define LAST_RECV_FRAG_PRED(spc_struct, event_param, status) \ 1053{ \ 1054 RPC_CN_DBG_RTN_PRINTF(SERVER last_recv_frag_pred_macro ); \ 1055 if (RPC_CN_PKT_FLAGS (RPC_CN_FRAGBUF_PKT_HDR (event_param)) & \ 1056 RPC_C_CN_FLAGS_LAST_FRAG) \ 1057 { \ 1058 status = 1; \ 1059 } \ 1060 else \ 1061 { \ 1062 status = 0; \ 1063 } \ 1064} 1065 1066 1067/* 1068**++ 1069** 1070** ROUTINE NAME: first_frag_pred_rtn 1071** 1072** SCOPE: INTERNAL 1073** 1074** DESCRIPTION: 1075** 1076** Evaluates whether a received packet has the first_frag bit 1077** set. 1078** 1079** INPUTS: 1080** 1081** spc_struct This argument is the special structure which 1082** is passed to the state machine event evaluation 1083** routine. 1084** This argument is ignored. 1085** 1086** event_param The received packet contained in a fragment 1087** buffer. This is passed in as the special 1088** event related parameter by the state machine 1089** event evaluation routine. 1090** 1091** INPUTS/OUTPUTS: none 1092** 1093** OUTPUTS: none 1094** 1095** IMPLICIT INPUTS: none 1096** 1097** IMPLICIT OUTPUTS: none 1098** 1099** FUNCTION VALUE: 0 if FirstFrag is false 1100** 1 if FirstFrag is true 1101** 1102** SIDE EFFECTS: none 1103** 1104**-- 1105**/ 1106 1107INTERNAL unsigned8 first_frag_pred_rtn 1108( 1109 dce_pointer_t spc_struct ATTRIBUTE_UNUSED, 1110 dce_pointer_t event_param 1111) 1112{ 1113 RPC_CN_DBG_RTN_PRINTF(SERVER first_frag_pred_rtn); 1114 1115 if (RPC_CN_PKT_FLAGS (RPC_CN_FRAGBUF_PKT_HDR (event_param)) & 1116 RPC_C_CN_FLAGS_FIRST_FRAG) 1117 { 1118 return (1); 1119 } 1120 else 1121 { 1122 return (2); 1123 } 1124 1125} 1126 1127 1128/* 1129**++ 1130** 1131** MACRO NAME: ALERTED_PRED 1132** 1133** SCOPE: INTERNAL 1134** 1135** DESCRIPTION: 1136** 1137** This is a macro of the alerted_pred_rtn routine 1138** introduced to avoid the overhead of a call-to-subroutine. 1139** Evaluates whether the current call has been alerted. 1140** 1141** INPUTS: 1142** 1143** spc_struct The call rep. Note that this is passed in as 1144** the special structure which is passed to the 1145** state machine event evaluation routine. 1146** 1147** status Instead of returning a value from the macro, 1148** write the value calculated in the macro to 1149** status. Status' scope includes the routine 1150** calling the macro. Check status in the calling 1151** routine to determine next state and in cases, 1152** flow through the action routine. 1153** 1154** INPUTS/OUTPUTS: none 1155** 1156** OUTPUTS: 1157** 1158** status See explanation above. 1159** 1160** IMPLICIT INPUTS: none 1161** 1162** IMPLICIT OUTPUTS: none 1163** 1164** FUNCTION VALUE: 0 if call was not alerted. 1165** 1 if call was alerted. 1166** 1167** SIDE EFFECTS: none 1168** 1169**-- 1170**/ 1171#define ALERTED_PRED(spc_struct, status)\ 1172{\ 1173 RPC_CN_DBG_RTN_PRINTF(SERVER alerted_pred_macro);\ 1174 if ( ((rpc_cn_call_rep_p_t) spc_struct)->cn_call_status ==\ 1175 rpc_s_call_cancelled )\ 1176 {\ 1177 status = 1;\ 1178 }\ 1179 else\ 1180 {\ 1181 status = 0;\ 1182 }\ 1183} 1184 1185 1186/***********************************************************************/ 1187/* 1188 * S E R V E R C A L L A C T I O N R O U T I N E S 1189 */ 1190/***********************************************************************/ 1191/* 1192**++ 1193** 1194** MACRO NAME: RPC_CN_ASSOC_QUEUE_FRAG 1195** 1196** SCOPE: INTERNAL 1197** 1198** DESCRIPTION: Used as an optimization. The macro function is 1199** called from several places and was included 1200** made into a macro for efficiency reasons. 1201** Called from handle_first_frag_action_rtn() 1202** and from handle_frag_action_rtn(). 1203** 1204** INPUTS: 1205** 1206** event_param The special event related parameter which is 1207** passed to the state machine event evaluation 1208** routine. 1209** This input argument is ignored. 1210** 1211** spc_struct The association group. Note that this is passed in as 1212** the special structure which is passed to the 1213** state machine event evaluation routine. 1214** 1215** fragbuf (rpc_cn_fragbuf_p_t)event_param. Used in 1216** the buffer manipulation routines called from 1217** within the macro. 1218** 1219** INPUTS/OUTPUTS: none 1220** 1221** OUTPUTS: none 1222** 1223** IMPLICIT INPUTS: none 1224** 1225** IMPLICIT OUTPUTS: none 1226** 1227** FUNCTION VALUE: 1228** 1229** SIDE EFFECTS: none 1230** 1231**-- 1232**/ 1233#define RPC_CN_ASSOC_QUEUE_FRAG(event_param, spc_struct, fragbuf) \ 1234{\ 1235 if ((RPC_CN_PKT_FLAGS (RPC_CN_FRAGBUF_PKT_HDR (event_param)) & \ 1236 RPC_C_CN_FLAGS_FIRST_FRAG)) \ 1237 { \ 1238 rpc__cn_assoc_queue_frag (((rpc_cn_call_rep_p_t) spc_struct)->assoc, \ 1239 fragbuf, \ 1240 false); \ 1241 } \ 1242 else \ 1243 { \ 1244 rpc__cn_assoc_queue_frag (((rpc_cn_call_rep_p_t) spc_struct)->assoc, \ 1245 fragbuf, \ 1246 true); \ 1247 } \ 1248} 1249 1250/* 1251**++ 1252** 1253** MACRO NAME: RPC_CN_FRAGBUF_DATA_SIZE 1254** 1255** SCOPE: INTERNAL 1256** 1257** DESCRIPTION: Used as an optimization. The macro function is 1258** called from several places and was included 1259** made into a macro for efficiency reasons. 1260** Called from handle_first_frag_action_rtn() 1261** and from handle_frag_action_rtn(). 1262** 1263** INPUTS: 1264** 1265** header_p RPC_CN_FRAGBUF_PKT_HDR (event_param) 1266** 1267** fragbuf (rpc_cn_fragbuf_p_t)event_param. Used in 1268** the buffer manipulation routines called from 1269** within the macro. 1270** 1271** INPUTS/OUTPUTS: none 1272** 1273** OUTPUTS: none 1274** 1275** IMPLICIT INPUTS: none 1276** 1277** IMPLICIT OUTPUTS: none 1278** 1279** FUNCTION VALUE: 1280** 1281** SIDE EFFECTS: none 1282** 1283**-- 1284**/ 1285#define RPC_CN_FRAGBUF_DATA_SIZE(header_p, fragbuf)\ 1286{\ 1287 if (RPC_CN_PKT_OBJ_UUID_PRESENT (header_p)) \ 1288 { \ 1289 if (RPC_CN_PKT_FRAG_LEN (header_p) < \ 1290 (RPC_CN_PKT_AUTH_TLR_LEN (header_p) + RPC_CN_PKT_SIZEOF_RQST_HDR_W_OBJ)) \ 1291 { \ 1292 DCETHREAD_RAISE(rpc_x_ss_pipe_comm_error); \ 1293 } \ 1294 fragbuf->data_size = RPC_CN_PKT_FRAG_LEN (header_p) - \ 1295 RPC_CN_PKT_AUTH_TLR_LEN (header_p) - \ 1296 RPC_CN_PKT_SIZEOF_RQST_HDR_W_OBJ; \ 1297 } \ 1298 else \ 1299 { \ 1300 if (RPC_CN_PKT_FRAG_LEN (header_p) < \ 1301 (RPC_CN_PKT_AUTH_TLR_LEN (header_p) + RPC_CN_PKT_SIZEOF_RQST_HDR_NO_OBJ)) \ 1302 { \ 1303 DCETHREAD_RAISE(rpc_x_ss_pipe_comm_error); \ 1304 } \ 1305 fragbuf->data_size = RPC_CN_PKT_FRAG_LEN (header_p) - \ 1306 RPC_CN_PKT_AUTH_TLR_LEN (header_p) - \ 1307 RPC_CN_PKT_SIZEOF_RQST_HDR_NO_OBJ; \ 1308 } \ 1309} 1310 1311 1312/* 1313**++ 1314** 1315** ROUTINE NAME: handle_first_frag_action_rtn 1316** 1317** SCOPE: INTERNAL 1318** 1319** DESCRIPTION: 1320** 1321** Make the received fragment data available to the stub for 1322** unmarshalling. The fragment is assumed to be the first 1323** fragment of the request. 1324** 1325** INPUTS: 1326** 1327** spc_struct The call rep. Note that this is passed in as 1328** the special structure which is passed to the 1329** state machine event evaluation routine. 1330** 1331** INPUTS/OUTPUTS: 1332** 1333** event_param The fragment buffer containing the received 1334** data. On output, the data_p and data_size 1335** fields will describe the stub data. 1336** 1337** sm The control block from the event evaluation 1338** routine. Input is the current state and 1339** event for the control block. Output is the 1340** next state or updated current state, for the 1341** control block. 1342** 1343** OUTPUTS: none 1344** 1345** IMPLICIT INPUTS: none 1346** 1347** IMPLICIT OUTPUTS: none 1348** 1349** FUNCTION VALUE: completion status, one of: 1350** rpc_s_ok, 1351** 1352** SIDE EFFECTS: none 1353** 1354**-- 1355**/ 1356INTERNAL unsigned32 handle_first_frag_action_rtn 1357( 1358 dce_pointer_t spc_struct, 1359 dce_pointer_t event_param, 1360 dce_pointer_t sm 1361) 1362{ 1363 unsigned32 status; 1364 rpc_cn_fragbuf_p_t request_fragbuf; 1365 rpc_cn_packet_p_t request_header_p; 1366 rpc_cn_packet_p_t response_header_p; 1367 rpc_cn_call_rep_p_t call_rep; 1368 rpc_cn_sm_ctlblk_t *sm_p; 1369 1370 RPC_CN_DBG_RTN_PRINTF(SERVER handle_first_frag_action_rtn); 1371 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 1372 call_rep = (rpc_cn_call_rep_p_t) spc_struct; 1373 request_fragbuf = (rpc_cn_fragbuf_p_t) event_param; 1374 request_header_p = RPC_CN_FRAGBUF_PKT_HDR (event_param); 1375 1376 /* 1377 * As part of the performance changes, we run a macro version 1378 * of the predicate function, last_recv_frag_pred_rtn() here. 1379 * Update status inside the macro. 1380 */ 1381 LAST_RECV_FRAG_PRED (spc_struct, event_param, status); 1382 if (status == 1) /* LastRecvFrag is true */ 1383 { 1384 sm_p->cur_state = RPC_C_SERVER_CALL_CALL_RESPONSE; 1385 } 1386 else /* LastRecvFrag is false */ 1387 { 1388 sm_p->cur_state = RPC_C_SERVER_CALL_CALL_REQUEST; 1389 } 1390 status = rpc_s_ok; 1391 1392 /* 1393 * Get the max_seg_size from the association. 1394 */ 1395 call_rep->max_seg_size = 1396 RPC_CN_ASSOC_MAX_XMIT_FRAG (call_rep->assoc); 1397 1398 /* 1399 * Copy the opnum field into the local call rep. 1400 */ 1401 call_rep->opnum = RPC_CN_PKT_OPNUM (request_header_p); 1402 if (!(RPC_CN_PKT_FLAGS (request_header_p) & RPC_C_CN_FLAGS_MAYBE)) 1403 { 1404 1405 /* 1406 * Fill in the fields of the response header if this is not 1407 * a maybe call. 1408 */ 1409 RPC_CN_CREP_SIZEOF_HDR (call_rep) = RPC_CN_PKT_SIZEOF_RESP_HDR; 1410 response_header_p = (rpc_cn_packet_p_t) RPC_CN_CREP_SEND_HDR (call_rep); 1411 1412 RPC_CN_PKT_PTYPE (response_header_p) = RPC_C_CN_PKT_RESPONSE; 1413 RPC_CN_PKT_FLAGS (response_header_p) = RPC_C_CN_FLAGS_FIRST_FRAG; 1414 RPC_CN_PKT_FRAG_LEN (response_header_p) = 0; 1415 RPC_CN_PKT_VERS_MINOR (response_header_p) = 1416 call_rep->assoc->assoc_vers_minor; 1417 RPC_CN_PKT_CALL_ID (response_header_p) = 1418 RPC_CN_PKT_CALL_ID (request_header_p); 1419 1420 RPC_CN_PKT_ALLOC_HINT (response_header_p) = 0; 1421 RPC_CN_PKT_PRES_CONT_ID (response_header_p) = 1422 RPC_CN_PKT_PRES_CONT_ID (request_header_p); 1423 1424 RPC_CN_PKT_RESP_RSVD (response_header_p) = 0; 1425 1426 /* 1427 * Initialize the iovector in the call_rep to contain only 1428 * one initial element, pointing to the protocol header. 1429 * Also, update pointers to show that we can copy data into 1430 * the stub data area. 1431 */ 1432 RPC_CN_CREP_IOVLEN (call_rep) = 1; 1433 RPC_CN_CREP_CUR_IOV_INDX (call_rep) = 0; 1434 RPC_CN_CREP_FREE_BYTES (call_rep) = 1435 RPC_C_CN_SMALL_FRAG_SIZE - RPC_CN_PKT_SIZEOF_RESP_HDR; 1436 RPC_CN_CREP_ACC_BYTCNT (call_rep) = RPC_CN_PKT_SIZEOF_RESP_HDR; 1437 RPC_CN_CREP_FREE_BYTE_PTR(call_rep) = 1438 RPC_CN_PKT_RESP_STUB_DATA (response_header_p); 1439 (RPC_CN_CREP_IOV (call_rep)[0]).data_len = RPC_CN_PKT_SIZEOF_RESP_HDR; 1440 1441 /* 1442 * If security is requested for this call an auth trailer will 1443 * be formatted here and included with every packet sent. 1444 */ 1445 if (call_rep->sec != NULL) 1446 { 1447 rpc_cn_auth_tlr_t *auth_tlr; 1448 unsigned32 auth_value_len; 1449 1450 /* 1451 * Allocate a small fragbuf to contain the authentication trailer. 1452 */ 1453 RPC_CN_FRAGBUF_ALLOC (call_rep->prot_tlr, RPC_C_CN_SMALL_FRAG_SIZE, &status); 1454 call_rep->prot_tlr->fragbuf_dealloc = NULL; 1455 auth_value_len = RPC_C_CN_SMALL_FRAG_SIZE; 1456 auth_tlr = (rpc_cn_auth_tlr_t *)call_rep->prot_tlr->data_p; 1457 auth_tlr->auth_type = RPC_CN_AUTH_CVT_ID_API_TO_WIRE (call_rep->sec->sec_info->authn_protocol, &status); 1458 auth_tlr->auth_level = call_rep->sec->sec_info->authn_level; 1459 auth_tlr->key_id = call_rep->sec->sec_key_id; 1460 auth_tlr->stub_pad_length = 0; 1461 auth_tlr->reserved = 0; 1462 RPC_CN_AUTH_PRE_CALL (RPC_CN_ASSOC_SECURITY (call_rep->assoc), 1463 call_rep->sec, 1464 (dce_pointer_t) auth_tlr->auth_value, 1465 &auth_value_len, 1466 &status); 1467 if (status != rpc_s_ok) 1468 { 1469 dce_error_string_t error_text; 1470 int temp_status; 1471 1472 dce_error_inq_text(status, error_text, &temp_status); 1473 1474 /* 1475 * "%s on server failed: %s" 1476 */ 1477 rpc_dce_svc_printf ( 1478 __FILE__, __LINE__, 1479 "%s %x", 1480 rpc_svc_auth, 1481 svc_c_sev_error, 1482 rpc_m_call_failed_s, 1483 "RPC_CN_AUTH_PRE_CALL", 1484 error_text ); 1485 1486 /* 1487 * A fault packet containing an appropriate status code 1488 * will be sent to the client in the receiver 1489 * thread. 1490 */ 1491 return (status); 1492 } 1493 RPC_CN_CREP_ADJ_IOV_FOR_TLR (call_rep, response_header_p, auth_value_len); 1494 } 1495 else 1496 { 1497 RPC_CN_PKT_AUTH_LEN (response_header_p) = 0; 1498 } 1499 } 1500 else 1501 { 1502 /* 1503 * There is no response packet for a maybe call. 1504 */ 1505 (RPC_CN_CREP_IOV (call_rep)[0]).data_len = 0; 1506 1507 /* 1508 * Even though there is no response for a maybe call, 1509 * we still set the flag bit because the server call state 1510 * machine predicates check it. 1511 */ 1512 RPC_CN_CREP_SIZEOF_HDR (call_rep) = RPC_CN_PKT_SIZEOF_RESP_HDR; 1513 response_header_p = (rpc_cn_packet_p_t) RPC_CN_CREP_SEND_HDR (call_rep); 1514 1515 RPC_CN_PKT_FLAGS (response_header_p) = RPC_C_CN_FLAGS_MAYBE; 1516 } 1517 1518 /* 1519 * Run the functional components of handle_frag_action_routine minus 1520 * its internal predicate component. 1521 */ 1522 /* 1523 * Adjust fragment buffer so that data_size describes the stub data. 1524 * Note that we do not adjust data_p; that will be done by 1525 * rpc__cn_call_receive. 1526 */ 1527 RPC_CN_FRAGBUF_DATA_SIZE(request_header_p, request_fragbuf); 1528 1529 /* 1530 * Queue the stub data on the association so that the call 1531 * executor thread can get it. 1532 * 1533 * As an optimization for the first fragment the association 1534 * receive queue condition variable will not be signalled since 1535 * the call executor thread is not started until after we return 1536 * from this state transition back to the receiver thread main loop. 1537 */ 1538 RPC_CN_ASSOC_QUEUE_FRAG(event_param, spc_struct, 1539 (rpc_cn_fragbuf_p_t) event_param); 1540 1541 /* 1542 * Check the header for a pending cancel. If we had a pending 1543 * cancel at the client side re-generate it here. 1544 */ 1545 if (RPC_CN_PKT_FLAGS (request_header_p) & RPC_C_CN_FLAGS_ALERT_PENDING) 1546 { 1547 RPC_DBG_PRINTF (rpc_e_dbg_cancel, RPC_C_CN_DBG_CANCEL, 1548 ("(handle_first_frag_action_rtn) call_rep->%p alert pending bit set in header calling rpc__cthread_cancel()\n", call_rep)); 1549 RPC_CALL_LOCK (((rpc_call_rep_t *) call_rep)); 1550 rpc__cthread_cancel ((rpc_call_rep_t *) call_rep); 1551 RPC_CALL_UNLOCK (((rpc_call_rep_t *) call_rep)); 1552 } 1553 return (status); 1554} 1555 1556 1557/* 1558**++ 1559** 1560** ROUTINE NAME: handle_frag_action_rtn 1561** 1562** SCOPE: INTERNAL 1563** 1564** DESCRIPTION: 1565** 1566** Make the received fragment data available to the stub for 1567** unmarshalling. 1568** 1569** INPUTS: 1570** 1571** spc_struct The call rep. Note that this is passed in as 1572** the special structure which is passed to the 1573** state machine event evaluation routine. 1574** 1575** INPUTS/OUTPUTS: 1576** 1577** event_param The fragment buffer containing the received 1578** data. On output, the data_p and data_size 1579** fields will describe the stub data. 1580** 1581** sm The control block from the event evaluation 1582** routine. Input is the current state and 1583** event for the control block. Output is the 1584** next state or updated current state, for the 1585** control block. 1586** 1587** OUTPUTS: none 1588** 1589** IMPLICIT INPUTS: none 1590** 1591** IMPLICIT OUTPUTS: none 1592** 1593** FUNCTION VALUE: rpc_s_ok 1594** 1595** SIDE EFFECTS: none 1596** 1597**-- 1598**/ 1599INTERNAL unsigned32 handle_frag_action_rtn 1600( 1601 dce_pointer_t spc_struct, 1602 dce_pointer_t event_param, 1603 dce_pointer_t sm 1604) 1605{ 1606 unsigned32 status; 1607 rpc_cn_fragbuf_p_t fragbuf; 1608 rpc_cn_packet_p_t header_p; 1609 rpc_cn_sm_ctlblk_t *sm_p; 1610 1611 RPC_CN_DBG_RTN_PRINTF(SERVER handle_frag_action_rtn); 1612 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 1613 fragbuf = (rpc_cn_fragbuf_p_t) event_param; 1614 header_p = RPC_CN_FRAGBUF_PKT_HDR (event_param); 1615 1616 /* 1617 * As part of the performance changes, we run a macro version 1618 * of the predicate function, last_recv_frag_pred_rtn() here. Update 1619 * status inside the macro. 1620 */ 1621 LAST_RECV_FRAG_PRED (spc_struct, event_param, status); 1622 if (status == 1) /* LastRecvFrag is true */ 1623 { 1624 sm_p->cur_state = RPC_C_SERVER_CALL_CALL_RESPONSE; 1625 } 1626 else /* LastRecvFrag is false */ 1627 { 1628 sm_p->cur_state = RPC_C_SERVER_CALL_CALL_REQUEST; 1629 } 1630 1631 status = rpc_s_ok; 1632 1633 /* 1634 * Adjust fragment buffer so that data_size describes the stub data. 1635 * Note that we do not adjust data_p; that will be done by 1636 * rpc__cn_call_receive. 1637 */ 1638 RPC_CN_FRAGBUF_DATA_SIZE(header_p, fragbuf); 1639 1640 /* 1641 * Queue the stub data on the association so that the call 1642 * executor thread can get it. 1643 * 1644 * As an optimization for the first fragment the association 1645 * receive queue condition variable will not be signalled since 1646 * the call executor thread is not started until after we return 1647 * from this state transition back to the receiver thread main loop. 1648 */ 1649 RPC_CN_ASSOC_QUEUE_FRAG(event_param, spc_struct, fragbuf); 1650 1651 return(status); 1652} 1653 1654 1655/* 1656**++ 1657** 1658** ROUTINE NAME: send_call_resp_action_rtn 1659** 1660** SCOPE: INTERNAL 1661** 1662** DESCRIPTION: 1663** 1664** Start sending the call response PDU(s) to the client. 1665** 1666** INPUTS: 1667** 1668** spc_struct The call rep. Note that this is passed in as 1669** the special structure which is passed to the 1670** state machine event evaluation routine. 1671** 1672** event_param The iovector describing the data to be sent. 1673** This is passed in as the special event related 1674** parameter passed to the state machine event 1675** evaluator. 1676** 1677** INPUTS/OUTPUTS: 1678** 1679** sm The control block from the event evaluation 1680** routine. Input is the current state and 1681** event for the control block. Output is the 1682** next state or updated current state, for the 1683** control block. 1684** 1685** OUTPUTS: none 1686** 1687** IMPLICIT INPUTS: none 1688** 1689** IMPLICIT OUTPUTS: none 1690** 1691** FUNCTION VALUE: rpc_s_ok if the send was completed successfully. 1692** 1693** SIDE EFFECTS: none 1694** 1695**-- 1696**/ 1697 1698INTERNAL unsigned32 send_call_resp_action_rtn 1699( 1700 dce_pointer_t spc_struct, 1701 dce_pointer_t event_param, 1702 dce_pointer_t sm 1703) 1704{ 1705 rpc_cn_call_rep_p_t call_rep; 1706 rpc_iovector_p_t stub_data_p; 1707 rpc_iovector_elt_p_t iov_elt_p; 1708 unsigned8 event ATTRIBUTE_UNUSED; 1709 unsigned32 i; 1710 unsigned32 status; 1711 rpc_cn_sm_ctlblk_t *sm_p; 1712 1713 RPC_CN_DBG_RTN_PRINTF(SERVER send_call_resp_action_rtn); 1714 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 1715 call_rep = (rpc_cn_call_rep_p_t) spc_struct; 1716 stub_data_p = (rpc_iovector_p_t) event_param; 1717 1718 /* 1719 * As part of the performance changes, we run a macro version 1720 * of the predicate function, disc_last_send_pred_rtn() here. Update 1721 * status inside the macro. Note that DISC_LAST_SEND_PRED 1722 * can only return 0 or 2, not 1. 1723 */ 1724 DISC_LAST_SEND_PRED(spc_struct, event_param, status ); 1725 sm_p->cur_state = RPC_C_SERVER_CALL_CALL_RESPONSE; 1726 if (status == 0) 1727 { 1728 abort_resp_action_rtn( spc_struct, event_param, sm); 1729 return(rpc_s_ok); 1730 } 1731 status = rpc_s_ok; 1732 1733 /* 1734 * A call_response must have some stub data. 1735 * 1736 * This raises a question: 1737 * If the call had no output arguments, then I guess 1738 * the CALL_END on the client would send back just 1739 * the protocol header. The runtime would have no 1740 * way of knowing until the CALL_END. Right? 1741 * Does this mean that we need to track whether any 1742 * response was generated and if not, issue just a 1743 * response header during a call end. 1744 */ 1745#ifdef DEBUG 1746 if ((stub_data_p == NULL) || (stub_data_p->num_elt <= 0)) 1747 { 1748 /* 1749 * rpc_m_no_stub_data 1750 * "(%s) No stub data to send" 1751 */ 1752 rpc_dce_svc_printf ( 1753 __FILE__, __LINE__, 1754 "%s", 1755 rpc_svc_xmit, 1756 svc_c_sev_fatal | svc_c_action_abort, 1757 rpc_m_no_stub_data, 1758 "send_call_resp_action_rtn" ); 1759 } 1760 else 1761 { 1762#endif 1763 /* Fill in the alloc_hint */ 1764 call_rep->alloc_hint = rpc__cn_get_alloc_hint(stub_data_p); 1765 1766 status = rpc_s_ok; 1767 for (i = 0, iov_elt_p = stub_data_p->elt; 1768 i < stub_data_p->num_elt; 1769 i++, iov_elt_p++) 1770 { 1771 /* 1772 * If there is no data, just deallocate the iovector 1773 * element. 1774 */ 1775 if (iov_elt_p->data_len <= 0) 1776 { 1777 if (iov_elt_p->buff_dealloc != NULL) 1778 { 1779 (iov_elt_p->buff_dealloc) (iov_elt_p->buff_addr); 1780 } 1781 } 1782 /* 1783 * If the number of bytes < our bcopy_lim, copy the data 1784 and deallocate the buffer. rpc__cn_copy_buffer will 1785 automatically transfer the data if the accumulated byte 1786 count reaches the segment size. 1787 */ 1788 else if (iov_elt_p->data_len <= RPC_C_CN_BCOPY_LIM) 1789 { 1790 rpc__cn_copy_buffer (call_rep, iov_elt_p, &status); 1791 if (iov_elt_p->buff_dealloc != NULL) 1792 { 1793 (iov_elt_p->buff_dealloc) (iov_elt_p->buff_addr); 1794 } 1795 } 1796 /* 1797 * If the buffer must be made immediately reusable, copy 1798 * it also. 1799 * Note that this can be optimized later so that we won't 1800 * copy; just transmit the data; if certain criteria have 1801 * been met. 1802 */ 1803 else if (iov_elt_p->flags & rpc_c_iovector_elt_reused) 1804 { 1805 rpc__cn_copy_buffer (call_rep, iov_elt_p, &status); 1806 if (status != rpc_s_ok) 1807 { 1808 return (status); 1809 } 1810 } 1811 else 1812 { 1813 /* 1814 * Don't copy, add this buffer as a new iovector 1815 * element. rpc__cnadd_new_vector_elmt will 1816 * automatically transfer the data if the 1817 * accumulated byte count reaches the segment size. 1818 */ 1819 rpc__cn_add_new_iovector_elmt (call_rep, iov_elt_p, &status); 1820 1821 if (status != rpc_s_ok) 1822 { 1823 return (status); 1824 } 1825 } 1826 } 1827#ifdef DEBUG 1828 } 1829#endif 1830 return (status); 1831} 1832 1833 1834/* 1835**++ 1836** 1837** ROUTINE NAME: send_call_fault_action_rtn 1838** 1839** SCOPE: INTERNAL 1840** 1841** DESCRIPTION: 1842** 1843** Start sending the call fault PDU(s) to the server. 1844** 1845** INPUTS: 1846** 1847** spc_struct The call rep. Note that this is passed in as 1848** the special structure which is passed to the 1849** state machine event evaluation routine. 1850** 1851** event_param The iovector describing the fault data 1852** to be sent. This is passed in as the special 1853** event related parameter passed to the state 1854** machine event evaluator. 1855** This parameter can be null. 1856** 1857** INPUTS/OUTPUTS: 1858** 1859** sm The control block from the event evaluation 1860** routine. Input is the current state and 1861** event for the control block. Output is the 1862** next state or updated current state, for the 1863** control block. 1864** 1865** OUTPUTS: none 1866** 1867** IMPLICIT INPUTS: call_rep->cn_call_status is assumed to 1868** indicate the cause of the fault. If it is 1869** 0, then it is assumed that there is 1870** fault data to be sent. 1871** 1872** IMPLICIT OUTPUTS: none 1873** 1874** FUNCTION VALUE: rpc_s_ok if the send was completed successfully. 1875** 1876** SIDE EFFECTS: none 1877** 1878**-- 1879**/ 1880INTERNAL unsigned32 send_call_fault_action_rtn 1881( 1882 dce_pointer_t spc_struct, 1883 dce_pointer_t event_param, 1884 dce_pointer_t sm 1885) 1886{ 1887 rpc_cn_call_rep_p_t call_rep; 1888 rpc_cn_packet_p_t header_p; 1889 rpc_iovector_p_t stub_data_p; 1890 rpc_iovector_elt_p_t iov_elt_p; 1891 unsigned32 i; 1892 unsigned32 status; 1893 unsigned32 pdu_size; 1894 rpc_cn_sm_ctlblk_t *sm_p; 1895 1896 RPC_CN_DBG_RTN_PRINTF(SERVER send_call_fault_action_rtn); 1897 1898 status = rpc_s_ok; 1899 1900 call_rep = (rpc_cn_call_rep_p_t) spc_struct; 1901 stub_data_p = (rpc_iovector_p_t) event_param; 1902 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 1903 1904 /* 1905 * As part of the performance changes, we run a macro version 1906 * of the predicate function, request_fault_pred_rtn() here. Update 1907 * status inside the macro. 1908 */ 1909 REQUEST_FAULT_PRED (call_rep, event_param, status); 1910 if (status == 0) 1911 { 1912 /* 1913 * abort_receive () is defined as RPC_C_SM_NO_ACTION 1914 */ 1915 sm_p->cur_state = RPC_C_SERVER_CALL_CALL_COMPLETED; 1916 return(status); 1917 } 1918 else if (status == 1) 1919 { 1920 sm_p->cur_state = RPC_C_SERVER_CALL_CALL_COMPLETED; 1921 } 1922 else if (status == 2) 1923 { 1924 sm_p->cur_state = RPC_C_SERVER_CALL_CALL_RESPONSE; 1925 } 1926 status = rpc_s_ok; 1927 1928 /* 1929 * Use the packet header bufferred on the call rep to format the 1930 * fault packet header. 1931 */ 1932 header_p = (rpc_cn_packet_p_t) RPC_CN_CREP_SEND_HDR (call_rep); 1933 1934 /* 1935 * The call is going to be terminated. The stub data bufferred 1936 * on the call rep will not be sent and can be released. 1937 */ 1938 rpc__cn_dealloc_buffered_data (call_rep); 1939 RPC_CN_FREE_ALL_EXCEPT_PROT_HDR (call_rep); 1940 1941 /* 1942 * Adjust the bufferred header to be the size of a fault packet 1943 * header. 1944 */ 1945 if (call_rep->sec == NULL) 1946 { 1947 pdu_size = RPC_CN_PKT_SIZEOF_FAULT_HDR; 1948 } 1949 else 1950 { 1951 pdu_size = 1952 RPC_CN_PKT_SIZEOF_FAULT_HDR + 1953 call_rep->prot_tlr->data_size; 1954 RPC_CN_CREP_IOVLEN (call_rep) = 2; 1955 } 1956 RPC_CN_CREP_SIZEOF_HDR (call_rep) = pdu_size; 1957 RPC_CN_CREP_IOV(call_rep)[0].data_len = pdu_size; 1958 RPC_CN_CREP_ACC_BYTCNT (call_rep) = pdu_size; 1959 1960 /* 1961 * Now set up the fault packet header. 1962 */ 1963 RPC_CN_PKT_PTYPE (header_p) = RPC_C_CN_PKT_FAULT; 1964 if (call_rep->call_executed) 1965 { 1966 RPC_CN_PKT_FLAGS (header_p) = RPC_C_CN_FLAGS_FIRST_FRAG; 1967 } 1968 else 1969 { 1970 RPC_CN_PKT_FLAGS (header_p) = RPC_C_CN_FLAGS_DID_NOT_EXECUTE | 1971 RPC_C_CN_FLAGS_FIRST_FRAG; 1972 } 1973 RPC_CN_PKT_ALLOC_HINT (header_p) = 0; 1974 RPC_CN_PKT_PRES_CONT_ID (header_p) = call_rep->context_id; 1975 RPC_CN_PKT_RESP_RSVD (header_p) = 0; 1976 RPC_CN_PKT_RESP_RSVD2 (header_p) = 0; 1977 1978 /* 1979 * The fault status can be either an architected non-zero 1980 * value indicating a runtime error, such as an interface 1981 * version mismatch, or zero, indicating a stub defined 1982 * exception specified with the stub data. 1983 */ 1984 if (call_rep->cn_call_status != rpc_s_ok) 1985 { 1986 RPC_CN_PKT_STATUS (header_p) = call_rep->cn_call_status; 1987 } 1988 else 1989 { 1990 RPC_CN_PKT_STATUS (header_p) = 0; 1991 1992#ifdef DEBUG 1993 /* 1994 * There should be stub data in this case. 1995 */ 1996 if ((stub_data_p == NULL) || (stub_data_p->num_elt <= 0)) 1997 { 1998 /* 1999 * rpc_m_no_stub_data 2000 * "(%s) No stub data to send" 2001 */ 2002 rpc_dce_svc_printf ( 2003 __FILE__, __LINE__, 2004 "%s", 2005 rpc_svc_xmit, 2006 svc_c_sev_fatal | svc_c_action_abort, 2007 rpc_m_no_stub_data, 2008 "send_call_fault_action_rtn" ); 2009 } 2010#endif 2011 2012 /* 2013 * Chain the fault data onto the buffered output. 2014 */ 2015 assert(stub_data_p != NULL); 2016 for (i = 0, iov_elt_p = stub_data_p->elt; 2017 i < stub_data_p->num_elt; 2018 i++, iov_elt_p++) 2019 { 2020 rpc__cn_add_new_iovector_elmt (call_rep, 2021 iov_elt_p, 2022 &status); 2023 if (status != rpc_s_ok) 2024 { 2025 rpc__cn_dealloc_buffered_data (call_rep); 2026 return (status); 2027 } 2028 } 2029 } 2030 2031 /* 2032 * We can only handle one fragment of fault data. 2033 */ 2034 RPC_CN_PKT_FLAGS (header_p) |= RPC_C_CN_FLAGS_LAST_FRAG; 2035 2036 /* 2037 * Update the alert_pending state and stop accepting 2038 * forwarded cancels. 2039 */ 2040 RPC_DBG_PRINTF (rpc_e_dbg_cancel, RPC_C_CN_DBG_CANCEL, 2041 ("(send_call_fault_action_rtn) call_rep->%p setting alert count (%d) in packet header\n", 2042 call_rep, 2043 call_rep->u.server.cancel.local_count)); 2044 RPC_CN_PKT_ALERT_COUNT (header_p) = call_rep->u.server.cancel.local_count; 2045 RPC_CALL_LOCK (((rpc_call_rep_t *) call_rep)); 2046 if (call_rep->common.u.server.cancel.had_pending) 2047 { 2048 RPC_DBG_PRINTF (rpc_e_dbg_cancel, RPC_C_CN_DBG_CANCEL, 2049 ("(send_call_fault_action_rtn) call_rep->%p setting alert pending bit in packet header\n", call_rep)); 2050 RPC_CN_PKT_FLAGS (header_p) |= RPC_C_CN_FLAGS_ALERT_PENDING; 2051 } 2052 RPC_CALL_UNLOCK (((rpc_call_rep_t *) call_rep)); 2053 rpc__cn_transmit_buffers (call_rep, &status); 2054 rpc__cn_dealloc_buffered_data (call_rep); 2055 RPC_CN_CREP_IOVLEN (call_rep) = 1; 2056 return (status); 2057} 2058 2059 2060/* 2061**++ 2062** 2063** ROUTINE NAME: process_alert_msg_action_rtn 2064** 2065** SCOPE: INTERNAL 2066** 2067** DESCRIPTION: 2068** 2069** Process a received remote alert message. 2070** 2071** INPUTS: 2072** 2073** spc_struct The call rep. Note that this is passed in as 2074** the special structure which is passed to the 2075** state machine event evaluation routine. 2076** 2077** event_param The fragment buffer containing the remote 2078** alert message. This fragment buffer is 2079** deallocated. 2080** 2081** INPUTS/OUTPUTS: 2082** 2083** sm The control block from the event evaluation 2084** routine. Input is the current state and 2085** event for the control block. Output is the 2086** next state or updated current state, for the 2087** control block. 2088** 2089** OUTPUTS: none 2090** 2091** IMPLICIT INPUTS: none 2092** 2093** IMPLICIT OUTPUTS: none 2094** 2095** FUNCTION VALUE: rpc_s_ok. 2096** 2097** SIDE EFFECTS: none 2098** 2099**-- 2100**/ 2101INTERNAL unsigned32 process_alert_msg_action_rtn 2102( 2103 dce_pointer_t spc_struct, 2104 dce_pointer_t event_param, 2105 dce_pointer_t sm 2106) 2107{ 2108 rpc_cn_call_rep_p_t call_rep; 2109 rpc_cn_fragbuf_p_t fragbuf; 2110 unsigned32 status ATTRIBUTE_UNUSED; 2111 rpc_cn_sm_ctlblk_t *sm_p; 2112 2113 RPC_CN_DBG_RTN_PRINTF(SERVER process_alert_msg_action_rtn); 2114 2115 call_rep = (rpc_cn_call_rep_p_t) spc_struct; 2116 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 2117 /* 2118 * Increment the number of remote cancels received. 2119 */ 2120 call_rep->u.server.cancel.local_count++; 2121 2122 RPC_DBG_PRINTF (rpc_e_dbg_cancel, RPC_C_CN_DBG_CANCEL, 2123 ("(process_alert_msg_action_rtn) call_rep->%p received remote alert packet total = %d\n", 2124 call_rep, 2125 call_rep->u.server.cancel.local_count)); 2126 2127 /* 2128 * We are currently executing in the context of the 2129 * receiver thread so call cthread_cancel. This routine will 2130 * cancel the call executor thread if the server is accepting and 2131 * not queueing cancels. 2132 */ 2133 RPC_CALL_LOCK (((rpc_call_rep_t *) call_rep)); 2134 rpc__cthread_cancel ((rpc_call_rep_t *) call_rep); 2135 RPC_CALL_UNLOCK (((rpc_call_rep_t *) call_rep)); 2136 2137 /* 2138 * We can just deallocate the fragment buffer. 2139 */ 2140 fragbuf = (rpc_cn_fragbuf_p_t) event_param; 2141 (* fragbuf->fragbuf_dealloc) (fragbuf); 2142 2143 /* 2144 * In this case, the updated value of sm->cur_state is 2145 * determined by the current value of sm->cur_state. 2146 * Note that 2+rpc_c_cn_statebase is call_response_state; 2147 * 1+rpc_c_cn_statebase is call_request_state. rpc_c_ 2148 * cn_statbase is used to distinguish state values from 2149 * action routine indexes in the state tables. 2150 */ 2151 if (sm_p->cur_state == (2 + RPC_C_CN_STATEBASE )) 2152 sm_p->cur_state = RPC_C_SERVER_CALL_CALL_RESPONSE; 2153 else if (sm_p->cur_state == ( 1 + RPC_C_CN_STATEBASE )) 2154 sm_p->cur_state = RPC_C_SERVER_CALL_CALL_REQUEST; 2155 return( rpc_s_ok); 2156} 2157 2158 2159/* 2160**++ 2161** 2162** ROUTINE NAME: abort_resp_action_rtn 2163** 2164** SCOPE: INTERNAL 2165** 2166** DESCRIPTION: 2167** 2168** Discontinue any further transmission of data for the current 2169** call, to the best extent possible. Some error condition has 2170** terminated the current call. 2171** 2172** INPUTS: 2173** 2174** spc_struct The call rep. Note that this is passed in as 2175** the special structure which is passed to the 2176** state machine event evaluation routine. 2177** 2178** event_param If not null, this is the address of an 2179** iovector. 2180** 2181** INPUTS/OUTPUTS: 2182** 2183** sm The control block from the event evaluation 2184** routine. Input is the current state and 2185** event for the control block. SM is not changed 2186** here. 2187** 2188** OUTPUTS: none 2189** 2190** IMPLICIT INPUTS: none 2191** 2192** IMPLICIT OUTPUTS: none 2193** 2194** FUNCTION VALUE: rpc_s_ok. 2195** 2196** SIDE EFFECTS: none 2197** 2198**-- 2199**/ 2200INTERNAL unsigned32 abort_resp_action_rtn 2201( 2202 dce_pointer_t spc_struct, 2203 dce_pointer_t event_param ATTRIBUTE_UNUSED, 2204 dce_pointer_t sm ATTRIBUTE_UNUSED 2205) 2206{ 2207 rpc_cn_call_rep_p_t call_rep; 2208 rpc_cn_packet_p_t header_p ATTRIBUTE_UNUSED; 2209 2210 RPC_CN_DBG_RTN_PRINTF(SERVER abort_resp_action_rtn); 2211 2212 call_rep = (rpc_cn_call_rep_p_t) spc_struct; 2213 2214 /* 2215 * If there are buffered iovector elements, deallocate them. 2216 * 2217 * Note that the comparison below is not strictly correct. 2218 * Even if there is only a single iovector element, there 2219 * may be copied stub data after the header. It's ok to 2220 * ignore them because the only way in which the first 2221 * iovector element would be reused is if we use it to send 2222 * a fault. That operation would adjust the pointers 2223 * anyway to point to only the fault data. 2224 */ 2225 if (RPC_CN_CREP_IOVLEN (call_rep) > 1) 2226 { 2227 rpc__cn_dealloc_buffered_data (call_rep); 2228 2229 /* 2230 * This will keep the call_end_action_rtn from attempting to 2231 * send the remaining iov which at this point is only an auth_tlr 2232 * if this was an authenticated call. We are calling this an 2233 * orphaned call which technically, it is, ie the connection is 2234 * gone and along with it the association. 2235 */ 2236 call_rep->cn_call_status = rpc_s_call_orphaned ; 2237 2238 /* 2239 * Set the length of the iovector to be 1 (just the 2240 * protocol header); everything else has been 2241 * deallocated. 2242 * 2243 * Note that we don't use the FREE_ALL_EXCEPT_PROT_HEADER 2244 * macro from cnxfer.c since we know that we won't be 2245 * queueing more data. 2246 */ 2247 RPC_CN_CREP_IOVLEN (call_rep) = 1; 2248 } 2249 2250 return (rpc_s_ok); 2251} 2252 2253 2254/* 2255**++ 2256** 2257** ROUTINE NAME: abort_resp_send_fault_action_rtn 2258** 2259** SCOPE: INTERNAL 2260** 2261** DESCRIPTION: 2262** 2263** Discontinue any further transmission of data for the current 2264** call, to the best extent possible; then send a fault. 2265** Some error condition has terminated the current call. 2266** 2267** INPUTS: 2268** 2269** spc_struct The call rep. Note that this is passed in as 2270** the special structure which is passed to the 2271** state machine event evaluation routine. 2272** 2273** event_param If not null, this is the address of an 2274** iovector element containing fault data. 2275** 2276** INPUTS/OUTPUTS: 2277** 2278** sm The control block from the event evaluation 2279** routine. Input is the current state and 2280** event for the control block. Output is the 2281** next state or updated current state, for the 2282** control block. 2283** 2284** OUTPUTS: none 2285** 2286** IMPLICIT INPUTS: none 2287** 2288** IMPLICIT OUTPUTS: none 2289** 2290** FUNCTION VALUE: rpc_s_ok. 2291** 2292** SIDE EFFECTS: none 2293** 2294**-- 2295**/ 2296INTERNAL unsigned32 abort_resp_send_fault_action_rtn 2297( 2298 dce_pointer_t spc_struct, 2299 dce_pointer_t event_param, 2300 dce_pointer_t sm 2301) 2302{ 2303 unsigned32 status; 2304 rpc_cn_sm_ctlblk_t *sm_p; 2305 unsigned8 n_state ATTRIBUTE_UNUSED; 2306 rpc_cn_packet_p_t header_p; 2307 rpc_cn_call_rep_p_t call_rep; 2308 rpc_iovector_elt_p_t iov_elt_p; 2309 rpc_iovector_p_t stub_data_p; 2310 unsigned32 i; 2311 unsigned32 pdu_size; 2312 2313 RPC_CN_DBG_RTN_PRINTF(SERVER abort_resp_send_fault_action_rtn); 2314 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 2315 2316 /* 2317 * RESPONSE_FAULT_PRED sets status which is used here 2318 * to determine the updated state in the control block, 2319 * and to determine which action routines (if any) 2320 * to call next. 2321 */ 2322 RESPONSE_FAULT_PRED(spc_struct, event_param, status); 2323 if (status == 0) /* MaybeSemantics true */ 2324 { 2325 sm_p->cur_state = RPC_C_SERVER_CALL_CALL_COMPLETED; 2326 return (rpc_s_ok); 2327 } 2328 else if (status == 1) /* Disconnected is true */ 2329 { 2330 abort_resp_action_rtn (spc_struct, event_param, sm); 2331 sm_p->cur_state = RPC_C_SERVER_CALL_CALL_COMPLETED; 2332 return (rpc_s_ok); 2333 } 2334 else if (status == 2) /* Otherwise.. */ 2335 { 2336 sm_p->cur_state = RPC_C_SERVER_CALL_CALL_COMPLETED; 2337 } 2338 2339 /* 2340 * REMOVED: this should be called acording to the spec, 2341 * but it doesn't do anything that isn't done already, 2342 * and it now sets the call status to orphaned. 2343 * 2344 * Abort the send; we don't care about its returned status. 2345 * status = abort_resp_action_rtn (spc_struct, event_param); 2346 */ 2347 2348 /* 2349 * Send the fault. 2350 * 2351 * send_call_fault_action_rtn (spc_struct, event_param ); 2352 * We changed send_call_fault_action_rtn to include a predicate 2353 * for performance reasons so we cannot just call the routine 2354 * here because the predicate function would cause additional 2355 * and incorrect state transitions. 2356 */ 2357 RPC_CN_DBG_RTN_PRINTF(SERVER send_call_fault_action_rtn); 2358 2359 call_rep = (rpc_cn_call_rep_p_t)spc_struct; 2360 stub_data_p = (rpc_iovector_p_t) event_param; 2361 2362 /* 2363 * Use the packet header bufferred on the call rep to format the 2364 * fault packet header. 2365 */ 2366 header_p = (rpc_cn_packet_p_t) RPC_CN_CREP_SEND_HDR (call_rep); 2367 2368 /* 2369 * The call is going to be terminated. The stub data bufferred 2370 * on the call rep will not be sent and can be released. 2371 */ 2372 rpc__cn_dealloc_buffered_data (call_rep); 2373 RPC_CN_FREE_ALL_EXCEPT_PROT_HDR (call_rep); 2374 2375 /* 2376 * Adjust the bufferred header to be the size of a fault packet 2377 * header. 2378 */ 2379 if (call_rep->sec == NULL) 2380 { 2381 pdu_size = RPC_CN_PKT_SIZEOF_FAULT_HDR; 2382 } 2383 else 2384 { 2385 pdu_size = 2386 RPC_CN_PKT_SIZEOF_FAULT_HDR + 2387 call_rep->prot_tlr->data_size; 2388 RPC_CN_CREP_IOVLEN (call_rep) = 2; 2389 } 2390 RPC_CN_CREP_SIZEOF_HDR (call_rep) = pdu_size; 2391 RPC_CN_CREP_IOV(call_rep)[0].data_len = pdu_size; 2392 RPC_CN_CREP_ACC_BYTCNT (call_rep) = pdu_size; 2393 2394 /* 2395 * Now set up the fault packet header. 2396 */ 2397 RPC_CN_PKT_PTYPE (header_p) = RPC_C_CN_PKT_FAULT; 2398 if (call_rep->call_executed) 2399 { 2400 RPC_CN_PKT_FLAGS (header_p) = RPC_C_CN_FLAGS_FIRST_FRAG; 2401 } 2402 else 2403 { 2404 RPC_CN_PKT_FLAGS (header_p) = RPC_C_CN_FLAGS_DID_NOT_EXECUTE | 2405 RPC_C_CN_FLAGS_FIRST_FRAG; 2406 } 2407 RPC_CN_PKT_ALLOC_HINT (header_p) = 0; 2408 RPC_CN_PKT_PRES_CONT_ID (header_p) = call_rep->context_id; 2409 RPC_CN_PKT_RESP_RSVD (header_p) = 0; 2410 RPC_CN_PKT_RESP_RSVD2 (header_p) = 0; 2411 2412 /* 2413 * The fault status can be either an architected non-zero 2414 * value indicating a runtime error, such as an interface 2415 * version mismatch, or zero, indicating a stub defined 2416 * exception specified with the stub data. 2417 */ 2418 if (call_rep->cn_call_status != rpc_s_ok) 2419 { 2420 RPC_CN_PKT_STATUS (header_p) = call_rep->cn_call_status; 2421 } 2422 else 2423 { 2424 RPC_CN_PKT_STATUS (header_p) = 0; 2425 2426#ifdef DEBUG 2427 /* 2428 * There should be stub data in this case. 2429 */ 2430 if ((stub_data_p == NULL) || (stub_data_p->num_elt <= 0)) 2431 { 2432 /* 2433 * rpc_m_no_stub_data 2434 * "(%s) No stub data to send" 2435 */ 2436 rpc_dce_svc_printf ( 2437 __FILE__, __LINE__, 2438 "%s", 2439 rpc_svc_xmit, 2440 svc_c_sev_fatal | svc_c_action_abort, 2441 rpc_m_no_stub_data, 2442 "send_call_fault_action_rtn" ); 2443 } 2444#endif 2445 2446 /* 2447 * Chain the fault data onto the buffered output. 2448 */ 2449 assert(stub_data_p != NULL); 2450 for (i = 0, iov_elt_p = stub_data_p->elt; 2451 i < stub_data_p->num_elt; 2452 i++, iov_elt_p++) 2453 { 2454 rpc__cn_add_new_iovector_elmt (call_rep, 2455 iov_elt_p, 2456 &status); 2457 if (status != rpc_s_ok) 2458 { 2459 rpc__cn_dealloc_buffered_data (call_rep); 2460 return(status); 2461 } 2462 } 2463 } 2464 2465 /* 2466 * We can only handle one fragment of fault data. 2467 */ 2468 RPC_CN_PKT_FLAGS (header_p) |= RPC_C_CN_FLAGS_LAST_FRAG; 2469 2470 /* 2471 * Update the alert_pending state and stop accepting 2472 * forwarded cancels. 2473 */ 2474 RPC_DBG_PRINTF (rpc_e_dbg_cancel, RPC_C_CN_DBG_CANCEL, 2475 ("(send_call_fault_action_rtn) call_rep->%p setting alert count (%d) in packet header\n", 2476 call_rep, 2477 call_rep->u.server.cancel.local_count)); 2478 RPC_CN_PKT_ALERT_COUNT (header_p) = call_rep->u.server.cancel.local_count; 2479 RPC_CALL_LOCK (((rpc_call_rep_t *) call_rep)); 2480 if (call_rep->common.u.server.cancel.had_pending) 2481 { 2482 RPC_DBG_PRINTF (rpc_e_dbg_cancel, RPC_C_CN_DBG_CANCEL, 2483 ("(send_call_fault_action_rtn) call_rep->%p setting alert pending bit in packet header\n", call_rep)); 2484 RPC_CN_PKT_FLAGS (header_p) |= RPC_C_CN_FLAGS_ALERT_PENDING; 2485 } 2486 RPC_CALL_UNLOCK (((rpc_call_rep_t *) call_rep)); 2487 rpc__cn_transmit_buffers (call_rep, &status); 2488 rpc__cn_dealloc_buffered_data (call_rep); 2489 RPC_CN_CREP_IOVLEN (call_rep) = 1; 2490 return (status); 2491} 2492 2493 2494/* 2495**++ 2496** 2497** ROUTINE NAME: stop_orphan_action_rtn 2498** 2499** SCOPE: INTERNAL 2500** 2501** DESCRIPTION: 2502** 2503** Tell the stub to orphan the previous call. If it was executing, 2504** i.e., was still receiving for a pipe, alert it. Otherwise, 2505** discard the input data. If possible (not required), insure 2506** that no response or fault is returned for the orphaned call. 2507** 2508** INPUTS: 2509** 2510** spc_struct The call rep. Note that this is passed in as 2511** the special structure which is passed to the 2512** state machine event evaluation routine. 2513** 2514** event_param The fragment buffer containing the orphaned 2515** packet. This fragment buffer is deallocated. 2516** 2517** INPUTS/OUTPUTS: 2518** 2519** sm The control block from the event evaluation 2520** routine. Input is the current state and 2521** event for the control block. Output is the 2522** next state or updated current state, for the 2523** control block. 2524** 2525** OUTPUTS: none 2526** 2527** IMPLICIT INPUTS: none 2528** 2529** IMPLICIT OUTPUTS: none 2530** 2531** FUNCTION VALUE: rpc_s_ok. 2532** 2533** SIDE EFFECTS: none 2534** 2535**-- 2536**/ 2537 2538INTERNAL unsigned32 stop_orphan_action_rtn 2539( 2540 dce_pointer_t spc_struct, 2541 dce_pointer_t event_param, 2542 dce_pointer_t sm 2543) 2544{ 2545 rpc_cn_call_rep_p_t call_rep; 2546 rpc_cn_fragbuf_p_t fragbuf; 2547 unsigned32 status; 2548 rpc_binding_rep_t *binding_r; 2549 rpc_cn_assoc_p_t assoc; 2550 rpc_cn_sm_ctlblk_t *sm_p; 2551 2552 RPC_CN_DBG_RTN_PRINTF(SERVER stop_orphan_action_rtn); 2553 2554 call_rep = (rpc_cn_call_rep_p_t) spc_struct; 2555 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 2556 2557 /* 2558 * We are currently executing in the context of the 2559 * receiver thread. The call has been orphaned by the client. 2560 * Free all stub data buffered for sending up to this point. 2561 */ 2562 rpc__cn_dealloc_buffered_data (call_rep); 2563 RPC_CN_FREE_ALL_EXCEPT_PROT_HDR (call_rep); 2564 2565 /* 2566 * If the call is queued dequeue it otherwise cancel and wakeup the thread 2567 * it is executing in. 2568 */ 2569 status = rpc_s_ok; 2570 call_rep->cn_call_status = rpc_s_call_orphaned; 2571 if (rpc__cthread_dequeue((rpc_call_rep_t *) call_rep)) 2572 { 2573 RPC_DBG_PRINTF(rpc_e_dbg_orphan, RPC_C_CN_DBG_ORPHAN, 2574 ("(stop_orphan_action_rtn) call_rep->%p queued call ... dequeued call id = %x\n", 2575 call_rep, 2576 RPC_CN_PKT_CALL_ID ((rpc_cn_packet_p_t) RPC_CN_CREP_SEND_HDR(call_rep)))); 2577 binding_r = (rpc_binding_rep_t *) call_rep->binding_rep; 2578 RPC_CN_UNLOCK (); 2579 rpc__cn_call_end ((rpc_call_rep_p_t *) &call_rep, &status); 2580 RPC_CN_LOCK (); 2581 RPC_BINDING_RELEASE (&binding_r, &status); 2582 } 2583 else 2584 { 2585 /* 2586 * We need to cancel and wake up the call executor 2587 * thread. If the call executor thread is in the manager 2588 * routine the cancel may get through. If it is in the 2589 * runtime blocked on a call_receive cancels are disabled 2590 * and needs to be woken up. 2591 */ 2592 RPC_DBG_PRINTF(rpc_e_dbg_orphan, RPC_C_CN_DBG_ORPHAN, 2593 ("(stop_orphan_action_rtn) call_rep->%p running call ... cancelling and waking up call id = %x\n", 2594 call_rep, 2595 RPC_CN_PKT_CALL_ID ((rpc_cn_packet_p_t) RPC_CN_CREP_SEND_HDR(call_rep)))); 2596 2597 /* 2598 * Need to hold on to the assoc in a local variable since 2599 * rpc__cn_assoc_pop_call is going to NULL call_rep->assoc. 2600 * We'll pass the local variable to rpc__cn_assoc_dealloc and 2601 * use it for RPC_COND_SIGNAL. 2602 */ 2603 assoc = call_rep->assoc; 2604 2605 /* 2606 * Pop the call rep off the association. 2607 */ 2608 rpc__cn_assoc_pop_call (call_rep->assoc, call_rep); 2609 2610 /* 2611 * Deallocate the association. 2612 */ 2613 rpc__cn_assoc_dealloc (assoc, call_rep, &status); 2614 2615 /* 2616 * If the stub is waiting for more data, signal it (really 2617 * rpc__cn_assoc_receive_frag()) to wake up (and find out 2618 * it's been orphaned). 2619 */ 2620 if (assoc->assoc_msg_waiters > 0) 2621 { 2622 RPC_COND_SIGNAL (assoc->assoc_msg_cond, rpc_g_global_mutex); 2623 } 2624 2625 RPC_CALL_LOCK (((rpc_call_rep_t *) call_rep)); 2626 rpc__cthread_cancel ((rpc_call_rep_t *) call_rep); 2627 RPC_CALL_UNLOCK (((rpc_call_rep_t *) call_rep)); 2628 } 2629 2630 /* 2631 * Deallocate the fragment buffer containing the orphaned packet. 2632 */ 2633 fragbuf = (rpc_cn_fragbuf_p_t) event_param; 2634 (*fragbuf->fragbuf_dealloc) (fragbuf); 2635 2636 /* 2637 * We do not need to call CALL_END since the call_executor 2638 * thread will do so when it processes the cancel. 2639 */ 2640 sm_p->cur_state = RPC_C_SERVER_CALL_CALL_COMPLETED; 2641 return(status); 2642} 2643 2644 2645/* 2646**++ 2647** 2648** ROUTINE NAME: discard_fragment_action_rtn 2649** 2650** SCOPE: INTERNAL 2651** 2652** DESCRIPTION: 2653** 2654** Discard the received packet. This routine is invoked when we 2655** get an unexpected (but benign) PDU. 2656** 2657** INPUTS: 2658** 2659** spc_struct This is the special structure which is passed 2660** to the state machine event evaluation routine. 2661** This parameer is ignored. 2662** 2663** event_param The fragment buffer containing the received 2664** packet. This is passed in as the event 2665** specific parameter to the state machine 2666** event evaluation routine. 2667** 2668** INPUTS/OUTPUTS: 2669** 2670** sm The control block from the event evaluation 2671** routine. Input is the current state and 2672** event for the control block. SM is not changed 2673** here. 2674** 2675** OUTPUTS: none 2676** 2677** IMPLICIT INPUTS: none 2678** 2679** IMPLICIT OUTPUTS: none 2680** 2681** FUNCTION VALUE: rpc_s_ok. 2682** 2683** SIDE EFFECTS: none 2684** 2685**-- 2686**/ 2687INTERNAL unsigned32 discard_fragment_action_rtn 2688( 2689 dce_pointer_t spc_struct ATTRIBUTE_UNUSED, 2690 dce_pointer_t event_param, 2691 dce_pointer_t sm ATTRIBUTE_UNUSED 2692) 2693{ 2694 rpc_cn_fragbuf_p_t fragbuf_p; 2695 unsigned32 status; 2696 2697 RPC_CN_DBG_RTN_PRINTF(SERVER discard_fragment_action_rtn); 2698 2699 fragbuf_p = (rpc_cn_fragbuf_p_t) event_param; 2700 (* fragbuf_p->fragbuf_dealloc) (fragbuf_p); 2701 2702 status = rpc_s_ok; 2703 return (status); 2704} 2705 2706 2707/* 2708**++ 2709** 2710** ROUTINE NAME: call_end_action_rtn 2711** 2712** SCOPE: INTERNAL 2713** 2714** DESCRIPTION: 2715** 2716** Handle the call end event. 2717** 2718** INPUTS: 2719** 2720** spc_struct The call rep. Note that this is passed in as 2721** the special structure which is passed to the 2722** state machine event evaluation routine. 2723** 2724** event_param This parameter is ignored. 2725** 2726** INPUTS/OUTPUTS: 2727** 2728** sm The control block from the event evaluation 2729** routine. Input is the current state and 2730** event for the control block. Output is the 2731** next state or updated current state, for the 2732** control block. 2733** 2734** OUTPUTS: none 2735** 2736** IMPLICIT INPUTS: none 2737** 2738** IMPLICIT OUTPUTS: none 2739** 2740** FUNCTION VALUE: rpc_s_ok 2741** 2742** SIDE EFFECTS: none 2743** 2744**-- 2745**/ 2746INTERNAL unsigned32 call_end_action_rtn 2747( 2748 dce_pointer_t spc_struct, 2749 dce_pointer_t event_param ATTRIBUTE_UNUSED, 2750 dce_pointer_t sm 2751) 2752{ 2753 rpc_cn_call_rep_p_t call_rep; 2754 rpc_cn_packet_p_t header_p; 2755 unsigned32 status; 2756 rpc_cn_sm_ctlblk_t *sm_p; 2757 unsigned8 n_state ATTRIBUTE_UNUSED; 2758 2759 RPC_CN_DBG_RTN_PRINTF(SERVER call_end_action_rtn); 2760 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 2761 2762 /* 2763 * If state is call_request_state (1+rpc_c_cn_statebase), we 2764 * need to use the alerted_pred_rtn function. 2765 * If the state is call_response 2766 * (2+rpc_c_cn_statebase), then we use no predicate routine. 2767 * The value of the state is augmented with rpc_c_cn_statebase in 2768 * order to quickly distinguish it from action routine indexes 2769 * in the rpc_cn_sm_event_eval() routine. 2770 */ 2771 if (sm_p->cur_state == ( 1 + RPC_C_CN_STATEBASE )) 2772 { 2773 ALERTED_PRED(spc_struct, status); 2774 if ( status == 1) 2775 { 2776 sm_p->cur_state = RPC_C_SERVER_CALL_CALL_COMPLETED; 2777 } 2778 else 2779 { 2780 /* No action required here. */ 2781 sm_p->cur_state = RPC_C_SM_NO_NSTATE; 2782 return (status); 2783 } 2784 } /* end of call_request_state */ 2785 2786 else if(sm_p->cur_state == ( 2 + RPC_C_CN_STATEBASE )) 2787 sm_p->cur_state = RPC_C_SERVER_CALL_CALL_COMPLETED; 2788 2789 status = rpc_s_ok; 2790 2791 call_rep = (rpc_cn_call_rep_p_t) spc_struct; 2792 2793 /* 2794 * If this is not a maybe call; i.e., there is a cached 2795 * protocol header, and we have not call call_end to 2796 * clean up after some error condition; 2797 * then send the last fragment. 2798 * Note that if there is no stub data, we will still 2799 * send a header with the last_frag_bit set. 2800 */ 2801 if (((RPC_CN_CREP_IOV (call_rep)[0]).data_len) != 0) 2802 { 2803 header_p = (rpc_cn_packet_p_t) RPC_CN_CREP_SEND_HDR (call_rep); 2804 RPC_CN_PKT_FLAGS (header_p) |= RPC_C_CN_FLAGS_LAST_FRAG; 2805 2806 /* 2807 * Update the alert_pending state and stop accepting 2808 * forwarded cancels. 2809 */ 2810 RPC_DBG_PRINTF (rpc_e_dbg_cancel, RPC_C_CN_DBG_CANCEL, 2811 ("(call_end_action_rtn) call_rep->%p setting alert count (%d) in packet header\n", 2812 call_rep, 2813 call_rep->u.server.cancel.local_count)); 2814 RPC_CN_PKT_ALERT_COUNT (header_p) = call_rep->u.server.cancel.local_count; 2815 RPC_CALL_LOCK (((rpc_call_rep_t *) call_rep)); 2816 if (call_rep->common.u.server.cancel.had_pending) 2817 { 2818 RPC_DBG_PRINTF (rpc_e_dbg_cancel, RPC_C_CN_DBG_CANCEL, 2819 ("(call_end_action_rtn) call_rep->%p setting alert pending bit in packet header\n", call_rep)); 2820 RPC_CN_PKT_FLAGS (header_p) |= RPC_C_CN_FLAGS_ALERT_PENDING; 2821 } 2822 2823 RPC_CALL_UNLOCK (((rpc_call_rep_t *) call_rep)); 2824 2825 /* 2826 * Don't transmit if orphaned. 2827 */ 2828 if (call_rep->cn_call_status != rpc_s_call_orphaned) 2829 { 2830 rpc__cn_transmit_buffers (call_rep, &status); 2831 } 2832 2833 rpc__cn_dealloc_buffered_data (call_rep); 2834 2835 /* 2836 * Set the length of the iovector to be 1 (just the 2837 * protocol header); everything else has been 2838 * deallocated. 2839 * 2840 * Note that we don't use the FREE_ALL_EXCEPT_PROT_HEADER 2841 * macro from cnxfer.c since we know that we won't be 2842 * queueing more data. 2843 */ 2844 RPC_CN_CREP_IOVLEN (call_rep) = 1; 2845 } 2846 return (status); 2847} 2848 2849 2850/* 2851**++ 2852** 2853** ROUTINE NAME: rpc__cn_call_sm_protocol_error 2854** 2855** SCOPE: PRIVATE 2856** 2857** DESCRIPTION: 2858** 2859** Action routine invoked when an illegal transition is detected. 2860** This routine writes an error message to stdout and DIEs. 2861** 2862** INPUTS: 2863** 2864** spc_struct The special structure which is passed to the 2865** state machine event evaluation routine. 2866** This is assumed to be the call rep. 2867** 2868** event_param The event specific argument. 2869** 2870** INPUTS/OUTPUTS: none 2871** 2872** sm The control block from the event evaluation 2873** routine. Input is the current state and 2874** event for the control block. Output is the 2875** next state or updated current state, for the 2876** control block. 2877** 2878** OUTPUTS: none 2879** 2880** IMPLICIT INPUTS: none 2881** 2882** IMPLICIT OUTPUTS: none 2883** 2884** FUNCTION VALUE: unsigned32 2885** 2886** SIDE EFFECTS: output is printed on stdout. 2887** 2888**-- 2889**/ 2890PRIVATE unsigned32 rpc__cn_call_sm_protocol_error 2891( 2892 dce_pointer_t spc_struct, 2893 dce_pointer_t event_param ATTRIBUTE_UNUSED, 2894 dce_pointer_t sm 2895) 2896{ 2897 rpc_cn_call_rep_p_t call_rep; 2898 rpc_cn_sm_ctlblk_t *sm_p; 2899 2900 RPC_CN_DBG_RTN_PRINTF(rpc__cn_call_sm_protocol_error); 2901 2902 sm_p = (rpc_cn_sm_ctlblk_t *)sm; 2903 sm_p->cur_state = RPC_C_SM_NO_NSTATE; 2904 2905 call_rep = (rpc_cn_call_rep_p_t) spc_struct; 2906 2907 /* 2908 * "Illegal state transition detected in CN {client|server} call state 2909 * machine [cur_state: %d, cur_event: %d, call_rep: %x]" 2910 */ 2911 rpc_dce_svc_printf ( 2912 __FILE__, __LINE__, 2913 "%d %d %x", 2914 rpc_svc_cn_state, 2915 svc_c_sev_fatal | svc_c_action_abort, 2916 RPC_CALL_IS_SERVER( (rpc_call_rep_t *)call_rep ) ? 2917 rpc_m_cn_ill_state_trans_sr : rpc_m_cn_ill_state_trans_cr, 2918 call_rep->call_state.cur_state, 2919 call_rep->call_state.cur_event, 2920 call_rep ); 2921 /* FIXME: is this correct? */ 2922 return rpc_s_ok; 2923} 2924