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** ctxeectx.c 82** 83** FACILITY: 84** 85** IDL Stub Runtime Support 86** 87** ABSTRACT: 88** 89** Maintain callee stub's table of contexts 90** 91** 92*/ 93#if HAVE_CONFIG_H 94#include <config.h> 95#endif 96 97/* The ordering of the following 3 includes should NOT be changed! */ 98#include <dce/rpc.h> 99#include <dce/stubbase.h> 100#include <lsysdep.h> 101 102#include <dce/uuid.h> 103 104#include <ctxeertl.h> 105 106#ifndef DEBUG_VERBOSE 107# define NDEBUG 108#endif 109#include <assert.h> 110 111#ifdef PERFMON 112#include <dce/idl_log.h> 113#endif 114 115#ifdef CTXEETEST 116# include <stdio.h> 117# define DPRINT(ARGS) printf ARGS 118#else 119# define DPRINT(ARGS) 120#endif 121 122/******************************************************************************/ 123/* */ 124/* Set up CMA machinery required by context tables */ 125/* */ 126/******************************************************************************/ 127 128ndr_boolean rpc_ss_context_is_set_up = ndr_false; 129 130static RPC_SS_THREADS_ONCE_T context_once = RPC_SS_THREADS_ONCE_INIT; 131 132RPC_SS_THREADS_MUTEX_T rpc_ss_context_table_mutex; 133 134static void rpc_ss_init_context( 135 void 136) 137{ 138 /* Create mutex for context handle tables */ 139 RPC_SS_THREADS_MUTEX_CREATE( &rpc_ss_context_table_mutex ); 140 /* And initialize the tables */ 141 rpc_ss_init_callee_ctx_tables(); 142} 143 144void rpc_ss_init_context_once( 145 void 146) 147{ 148 RPC_SS_THREADS_INIT; 149 RPC_SS_THREADS_ONCE( &context_once, rpc_ss_init_context ); 150 rpc_ss_context_is_set_up = ndr_true; 151} 152 153/* Number of context slots in hash table. 154*/ 155#define CALLEE_CONTEXT_TABLE_SIZE 256 156 157static callee_context_entry_t *context_table = NULL; 158 159/* Allocate and initialize callee context and client lookup tables. 160*/ 161void rpc_ss_init_callee_ctx_tables( 162 void 163) 164{ 165 166#ifdef PERFMON 167 RPC_SS_INIT_CALLEE_CTX_TABLES_N; 168#endif 169 170 assert(!context_table); /* Must not be called more than once. */ 171 172 context_table = (callee_context_entry_t *)malloc( 173 CALLEE_CONTEXT_TABLE_SIZE * sizeof(callee_context_entry_t) 174 ); 175 176 if (!context_table) 177 DCETHREAD_RAISE(rpc_x_no_memory); 178 179/***************** 180** 181** The memset below has the same effect as this more descriptive loop. 182** 183** for (i = 0; i < CALLEE_CONTEXT_TABLE_SIZE; i++) { 184** uuid_create_nil(&context_table[i].uuid, &status); 185** context_table[i].next_context = NULL; 186** } 187** 188******************/ 189 190 memset (context_table, 0, 191 CALLEE_CONTEXT_TABLE_SIZE * sizeof(callee_context_entry_t)); 192 rpc_ss_init_callee_client_table(); 193 194#ifdef PERFMON 195 RPC_SS_INIT_CALLEE_CTX_TABLES_X; 196#endif 197 198} 199 200/******************************************************************************/ 201/* */ 202/* Add an entry to the callee context lookup table */ 203/* */ 204/******************************************************************************/ 205void rpc_ss_create_callee_context 206( 207 rpc_ss_context_t callee_context,/* The user's local form of the context */ 208 idl_uuid_t *p_uuid, /* Pointer to the equivalent UUID */ 209 handle_t h, /* Binding handle */ 210 ctx_rundown_fn_p_t ctx_rundown, /* Pointer to context rundown routine */ 211 error_status_t *result /* Function result */ 212) 213{ 214 rpc_client_handle_t ctx_client; /* ID of client owning context */ 215 callee_context_entry_t *this_link, *next_link, * volatile new_link; 216 ndr_boolean is_new_client; 217 218 //DO_NOT_CLOBBER(new_link); 219 220#ifdef PERFMON 221 RPC_SS_CREATE_CALLEE_CONTEXT_N; 222#endif 223 224 /* If this is the first context to be created, initialization is needed */ 225 RPC_SS_INIT_CONTEXT 226 227 rpc_binding_inq_client(h, &ctx_client, (error_status_t *) result); 228 if (*result != error_status_ok) return; 229 230 RPC_SS_THREADS_MUTEX_LOCK(&rpc_ss_context_table_mutex); 231 DPRINT(("Seized context tables\n")); 232 this_link = &context_table[uuid_hash(p_uuid,(error_status_t *)result) 233 % CALLEE_CONTEXT_TABLE_SIZE]; 234 if ( uuid_is_nil(&this_link->uuid, (error_status_t *)result) ) 235 { 236 /* Home slot in the hash table is empty */ 237 new_link = this_link; 238 next_link = NULL; 239 } 240 else 241 { 242 /* Put the new item at the head of the overflow chain */ 243 new_link = (callee_context_entry_t *) 244 malloc(sizeof(callee_context_entry_t)); 245 if (new_link == NULL) 246 { 247 RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); 248 DPRINT(("Released context tables\n")); 249 DCETHREAD_RAISE( rpc_x_no_memory ); 250 } 251 next_link = this_link->next_context; 252 this_link->next_context = new_link; 253 } 254 255 /* Fill in fields of context entry */ 256 memcpy( 257 (char *)&new_link->uuid, 258 (char *)p_uuid, 259 sizeof(idl_uuid_t) 260 ); 261 new_link->user_context = callee_context; 262 new_link->rundown = ctx_rundown; 263 new_link->next_context = next_link; 264 265 DCETHREAD_TRY 266 rpc_ss_add_to_callee_client(ctx_client,new_link,&is_new_client, 267 result); 268 DCETHREAD_FINALLY 269 RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); 270 DPRINT(("Released context tables\n")); 271 DCETHREAD_ENDTRY 272 if ((*result == error_status_ok) && is_new_client) 273 { 274 rpc_network_monitor_liveness( h, ctx_client, 275 rpc_ss_rundown_client, 276 (error_status_t *) result ); 277#ifdef PERFMON 278 RPC_SS_CREATE_CALLEE_CONTEXT_X; 279#endif 280 } 281} 282 283/******************************************************************************/ 284/* */ 285/* Update an entry in the callee context lookup table */ 286/* *result is error_status_ok unless the UUID is not in the lookup table. */ 287/* */ 288/******************************************************************************/ 289void rpc_ss_update_callee_context 290( 291 rpc_ss_context_t callee_context, /* The user's local form of the context */ 292 idl_uuid_t *p_uuid, /* Pointer to the equivalent UUID */ 293 error_status_t *result /* Function result */ 294) 295{ 296 callee_context_entry_t *this_link; 297 298#ifdef PERFMON 299 RPC_SS_UPDATE_CALLEE_CONTEXT_N; 300#endif 301 302 RPC_SS_THREADS_MUTEX_LOCK(&rpc_ss_context_table_mutex); 303 DPRINT(("Seized context tables\n")); 304 this_link = &context_table[uuid_hash(p_uuid,result) 305 % CALLEE_CONTEXT_TABLE_SIZE]; 306 while ( ! uuid_equal(p_uuid,&this_link->uuid,result) ) 307 { 308 this_link = this_link->next_context; 309 if (this_link == NULL) 310 { 311 RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); 312 DPRINT(("Released context tables\n")); 313 DCETHREAD_RAISE( rpc_x_ss_context_mismatch); 314 } 315 } 316 this_link->user_context = callee_context; 317 RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); 318 DPRINT(("Released context tables\n")); 319 *result = error_status_ok; 320 321#ifdef PERFMON 322 RPC_SS_UPDATE_CALLEE_CONTEXT_X; 323#endif 324 325} 326 327/******************************************************************************/ 328/* */ 329/* Find the local context that corresponds to a supplied UUID */ 330/* */ 331/* ENTRY POINT INTO LIBIDL FROM STUB */ 332/* */ 333/******************************************************************************/ 334void rpc_ss_ee_ctx_from_wire 335( 336 ndr_context_handle *p_wire_context, 337 rpc_ss_context_t *p_context, /* The application context */ 338 volatile error_status_t *p_st 339) 340{ 341 idl_uuid_t *p_uuid; /* Pointer to the UUID that has come off the wire */ 342 callee_context_entry_t *this_link; 343 344#ifdef PERFMON 345 RPC_SS_EE_CTX_FROM_WIRE_N; 346#endif 347 348 p_uuid = &p_wire_context->context_handle_uuid; 349 350#ifdef DEBUGCTX 351 debug_context_lookup(p_uuid); 352 debug_context_table(); 353#endif 354 355 *p_st = error_status_ok; 356 if ( uuid_is_nil(p_uuid, (error_status_t *)p_st) ) 357 { 358 *p_context = NULL; 359 360#ifdef PERFMON 361 RPC_SS_EE_CTX_FROM_WIRE_X; 362#endif 363 364 return; 365 } 366 RPC_SS_THREADS_MUTEX_LOCK(&rpc_ss_context_table_mutex); 367 DPRINT(("Seized context tables\n")); 368 this_link = &context_table[uuid_hash(p_uuid, (error_status_t *)p_st) 369 % CALLEE_CONTEXT_TABLE_SIZE]; 370 while ( ! uuid_equal(p_uuid,&this_link->uuid, (error_status_t *)p_st) ) 371 { 372 this_link = this_link->next_context; 373 if (this_link == NULL) 374 { 375 RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); 376 DPRINT(("Released context tables\n")); 377 378#ifdef PERFMON 379 RPC_SS_EE_CTX_FROM_WIRE_X; 380#endif 381 382 DCETHREAD_RAISE( rpc_x_ss_context_mismatch ); 383 return; 384 } 385 } 386 *p_context = this_link->user_context; 387 RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); 388 DPRINT(("Released context tables\n")); 389 390#ifdef PERFMON 391 RPC_SS_EE_CTX_FROM_WIRE_X; 392#endif 393 394 return; 395} 396 397/******************************************************************************/ 398/* */ 399/* Take a lock on the context tables and destroy a context entry */ 400/* */ 401/******************************************************************************/ 402void rpc_ss_destroy_callee_context 403( 404 idl_uuid_t *p_uuid, /* Pointer to UUID of context to be destroyed */ 405 handle_t h, /* Binding handle */ 406 error_status_t *result /* Function result */ 407) /* Returns error_status_ok unless the UUID is not in the lookup table */ 408{ 409 rpc_client_handle_t close_client; /* NULL or client to stop monitoring */ 410 411#ifdef PERFMON 412 RPC_SS_DESTROY_CALLEE_CONTEXT_N; 413#endif 414 415 RPC_SS_THREADS_MUTEX_LOCK(&rpc_ss_context_table_mutex); 416 DPRINT(("Seized context tables\n")); 417 rpc_ss_lkddest_callee_context(p_uuid,&close_client,result); 418 RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); 419 DPRINT(("Released context tables\n")); 420 if ((*result == error_status_ok) && (close_client != NULL)) 421 { 422 rpc_network_stop_monitoring(h, close_client, (error_status_t *) result); 423 } 424#ifdef PERFMON 425 RPC_SS_DESTROY_CALLEE_CONTEXT_X; 426#endif 427} 428 429/******************************************************************************/ 430/* */ 431/* Destroy an entry in the context table */ 432/* */ 433/* Assumes that the context table mutex is locked */ 434/* */ 435/******************************************************************************/ 436void rpc_ss_lkddest_callee_context 437( 438 idl_uuid_t *p_uuid, /* Pointer to UUID of context to be destroyed */ 439 rpc_client_handle_t *p_close_client, 440 /* Ptr to NULL or client to stop monitoring */ 441 error_status_t *result /* Function result */ 442) /* Returns error_status_ok unless the UUID is not in the lookup table */ 443{ 444 callee_context_entry_t *this_link, *next_link, *last_link; 445 446#ifdef PERFMON 447 RPC_SS_LKDDEST_CALLEE_CONTEXT_N; 448#endif 449 450 this_link = &context_table[uuid_hash(p_uuid,(error_status_t *) result) 451 % CALLEE_CONTEXT_TABLE_SIZE]; 452 next_link = this_link->next_context; 453 if ( uuid_equal(p_uuid,&this_link->uuid, (error_status_t *) result) ) 454 { 455 /* Context to be destroyed is in home slot */ 456 rpc_ss_take_from_callee_client(this_link,p_close_client,result); 457 if (next_link == NULL) 458 { 459 /* There is no chain from the home slot */ 460 uuid_create_nil(&this_link->uuid, (error_status_t *) result); 461 } 462 else 463 { 464 /* Move the second item in the chain to the home slot */ 465 memcpy( 466 (char *)&this_link->uuid, 467 (char *)&next_link->uuid, 468 sizeof(idl_uuid_t) 469 ); 470 this_link->user_context = next_link->user_context; 471 this_link->rundown = next_link->rundown; 472 this_link->p_client_entry = next_link->p_client_entry; 473 this_link->prev_in_client = next_link->prev_in_client; 474 if (this_link->prev_in_client == NULL) 475 { 476 (this_link->p_client_entry)->first_context = this_link; 477 } 478 else 479 { 480 (this_link->prev_in_client)->next_in_client = this_link; 481 } 482 this_link->next_in_client = next_link->next_in_client; 483 if (this_link->next_in_client == NULL) 484 { 485 (this_link->p_client_entry)->last_context = this_link; 486 } 487 else 488 { 489 (this_link->next_in_client)->prev_in_client = this_link; 490 } 491 this_link->next_context = next_link->next_context; 492 /* And release the memory it was in */ 493 free((char_p_t)next_link); 494 } 495 496#ifdef PERFMON 497 RPC_SS_LKDDEST_CALLEE_CONTEXT_X; 498#endif 499 500 return; 501 } 502 else /* Context is further down chain */ 503 { 504 while (next_link != NULL) 505 { 506 last_link = this_link; 507 this_link = next_link; 508 next_link = this_link->next_context; 509 if ( uuid_equal(p_uuid,&this_link->uuid,(error_status_t *)result) ) 510 { 511 rpc_ss_take_from_callee_client(this_link,p_close_client,result); 512 /* Relink chain to omit found entry */ 513 last_link->next_context = next_link; 514 /* And free the memory it occupied */ 515 free((char_p_t)this_link); 516 517#ifdef PERFMON 518 RPC_SS_LKDDEST_CALLEE_CONTEXT_X; 519#endif 520 521 return; 522 } 523 } 524 RPC_SS_THREADS_MUTEX_UNLOCK(&rpc_ss_context_table_mutex); 525 DPRINT(("Released context tables\n")); 526 DCETHREAD_RAISE( rpc_x_ss_context_mismatch); 527 } 528} 529 530#ifdef CTXEETEST 531void dump_context_table() 532{ 533 int i; 534 callee_context_entry_t *this_link; 535 callee_client_entry_t *this_client; 536 error_status_t status; 537 538 for (i=0; i<CALLEE_CONTEXT_TABLE_SIZE; i++) 539 { 540 if ( ! uuid_is_nil(&context_table[i].uuid, &status) ) 541 { 542 this_link = &context_table[i]; 543 printf("Context chain for context_slot %d\n",i); 544 while (this_link != NULL) 545 { 546 printf("\t %s %lx ", 547 &this_link->uuid, 548 this_link->user_context); 549 this_client = this_link->p_client_entry; 550 printf("Client %lx %d\n", 551 this_client->client, 552 this_client->count); 553 this_link = this_link->next_context; 554 } 555 } 556 } 557} 558#endif 559 560#ifdef DEBUGCTX 561static ndr_boolean debug_file_open = ndr_false; 562static char *debug_file = "ctxee.dmp"; 563static FILE *debug_fid; 564 565static int debug_context_lookup(uuid_p) 566 unsigned char *uuid_p; 567{ 568 int j; 569 unsigned long k; 570 571 if (!debug_file_open) 572 { 573 debug_fid = fopen(debug_file, "w"); 574 debug_file_open = ndr_true; 575 } 576 577 fprintf(debug_fid, "L"); 578 for (j=0; j<sizeof(idl_uuid_t); j++) 579 { 580 k = *uuid_p++; 581 fprintf(debug_fid, " %02x", k); 582 } 583 fprintf(debug_fid, "\n"); 584} 585 586static int debug_context_add(user_context) 587 long user_context; 588{ 589 if (!debug_file_open) 590 { 591 debug_fid = fopen(debug_file, "w"); 592 debug_file_open = ndr_true; 593 } 594 595 fprintf(debug_fid, "N %lx\n", user_context); 596} 597 598static int debug_context_table() 599{ 600 int i, j; 601 unsigned long k; 602 ndr_boolean at_home; 603 unsigned char *uuid_p; 604 callee_context_entry_t *this_link; 605 callee_client_entry_t *this_client; 606 error_status_t status; 607 608 if (!debug_file_open) 609 { 610 debug_fid = fopen(debug_file, "w"); 611 debug_file_open = ndr_true; 612 } 613 614 for (i=0; i<CALLEE_CONTEXT_TABLE_SIZE; i++) 615 { 616 if ( ! uuid_is_nil(&context_table[i].uuid, &status) ) 617 { 618 at_home = ndr_true; 619 this_link = &context_table[i]; 620 while (this_link != NULL) 621 { 622 if (at_home) 623 { 624 at_home = ndr_false; 625 fprintf(debug_fid, "%4d:", i); 626 } 627 else 628 fprintf(debug_fid, " C:", i); 629 uuid_p = (unsigned char *)&this_link->uuid; 630 for (j=0; j<sizeof(this_link->uuid); j++) 631 { 632 k = *uuid_p++; 633 fprintf(debug_fid, " %02x", k); 634 } 635 this_client = this_link->p_client_entry; 636 fprintf(debug_fid, " client %lx %d\n", 637 this_client->client, 638 this_client->count); 639 this_link = this_link->next_context; 640 } 641 } 642 } 643} 644#endif 645 646/******************************************************************************/ 647/* */ 648/* Routine to be called when a callee argument of type context_t is to */ 649/* be marshalled */ 650/* */ 651/* ENTRY POINT INTO LIBIDL FROM STUB */ 652/* */ 653/******************************************************************************/ 654void rpc_ss_ee_ctx_to_wire 655( 656 rpc_ss_context_t callee_context, /* The application context */ 657 ndr_context_handle *p_wire_context, /* Pointer to wire form of context */ 658 handle_t h, /* Binding handle */ 659 ctx_rundown_fn_p_t ctx_rundown, /* Pointer to context rundown routine */ 660 ndr_boolean in_out, /* TRUE for [in,out], FALSE for [out] */ 661 volatile error_status_t *p_st 662) 663{ 664#ifdef DEBUGCTX 665 debug_context_add(callee_context); 666#endif 667 668 int wire, context; 669 p_wire_context->context_handle_attributes = 0; /* Only defined value. */ 670 671 /* Boolean conditions are 672 * wire: UUID from wire is valid (not nil) -- in_out must be true. 673 * context: callee context from manager is valid (not NULL). 674 * in_out: context handle parameter is [in,out] (not just [out]). 675 * Mapping of conditions onto actions implemented in the following switch. 676 * wire context in_out condition Action 677 * 0 0 0 0 create nil UUID 678 * 0 0 1 1 do nothing -- use old (nil) UUID 679 * 0 1 0 2 create new UUID and new context 680 * 0 1 1 3 create new UUID and new context 681 * 1 0 0 4 impossible 682 * 1 0 1 5 destroy existing context, make UUID nil 683 * 1 1 0 6 impossible 684 * 1 1 1 7 update existing context 685 */ 686 687#ifdef PERFMON 688 RPC_SS_EE_CTX_TO_WIRE_N; 689#endif 690 691 wire = in_out && !uuid_is_nil( 692 &p_wire_context->context_handle_uuid, (error_status_t *)p_st 693 )? 4: 0; 694 context = callee_context? 2: 0; 695 in_out = in_out? 1: 0; 696 697 switch (wire | context | in_out) { 698 case 0: 699 uuid_create_nil( 700 &p_wire_context->context_handle_uuid, (error_status_t *)p_st 701 ); 702 break; 703 case 1: 704 *p_st = error_status_ok; 705 break; 706 case 2: 707 case 3: 708 uuid_create( 709 &p_wire_context->context_handle_uuid, (error_status_t *)p_st 710 ); 711 rpc_ss_create_callee_context( 712 callee_context, &p_wire_context->context_handle_uuid, h, 713 ctx_rundown, (error_status_t *)p_st 714 ); 715 break; 716 case 5: 717 rpc_ss_destroy_callee_context( 718 &p_wire_context->context_handle_uuid, h, (error_status_t *)p_st 719 ); 720 if (*p_st != error_status_ok) break; 721 uuid_create_nil( 722 &p_wire_context->context_handle_uuid, (error_status_t *)p_st 723 ); 724 break; 725 case 7: 726 rpc_ss_update_callee_context( 727 callee_context, &p_wire_context->context_handle_uuid, 728 (error_status_t *)p_st 729 ); 730 break; 731 default: /* All invalid conditions evaluate true. */ 732 assert(!(wire | context | in_out)); 733 break; 734 } 735 736#ifdef DEBUGCTX 737 debug_context_table(); 738#endif 739 740#ifdef PERFMON 741 RPC_SS_EE_CTX_TO_WIRE_X; 742#endif 743 744} 745