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** comobj.c 82** 83** FACILITY: 84** 85** Remote Procedure Call (RPC) 86** 87** ABSTRACT: 88** 89** Definition of the Object Services for the Common Communication 90** Services component. These routines are called by an application 91** to register objects and object types with the runtime. 92** 93** 94*/ 95 96#include <commonp.h> /* Common declarations for all RPC runtime */ 97#include <com.h> /* Public common communications services */ 98#include <comprot.h> /* Common protocol services */ 99#include <comnaf.h> /* Common network address family services */ 100#include <comp.h> /* Private common communications services */ 101 102/* 103 * the size of the object registry hash table 104 * - pick a prime number to avoid collisions 105 */ 106#define RPC_C_OBJ_REGISTRY_SIZE 31 107 108/* 109 * The Object Registry Table, where object/type pairs 110 * are registered, and upon which the routines contained within 111 * this module perform their actions. Protected by "obj_mutex". 112 */ 113INTERNAL rpc_list_t obj_registry[RPC_C_OBJ_REGISTRY_SIZE] = { {0,0} }; 114INTERNAL rpc_mutex_t obj_mutex; 115 116/* 117 * an object registry list entry 118 */ 119typedef struct 120{ 121 rpc_list_t link; 122 idl_uuid_t object_uuid; 123 idl_uuid_t type_uuid; 124} rpc_obj_rgy_entry_t, *rpc_obj_rgy_entry_p_t; 125 126/* 127 * Function registered by applicationthrough rpc_object_set_inq_fn. 128 */ 129INTERNAL rpc_object_inq_fn_t inq_fn = NULL; 130 131 132/* 133**++ 134** 135** ROUTINE NAME: rpc__obj_init 136** 137** SCOPE: PRIVATE - declared in com.h 138** 139** DESCRIPTION: 140** 141** Initializes this module. 142** 143** INPUTS: none 144** 145** INPUTS/OUTPUTS: none 146** 147** OUTPUTS: 148** 149** status The result of the operation. 150** 151** IMPLICIT INPUTS: none 152** 153** IMPLICIT OUTPUTS: none 154** 155** FUNCTION VALUE: void 156** 157** SIDE EFFECTS: none 158** 159**-- 160**/ 161 162PRIVATE void rpc__obj_init 163( 164 unsigned32 *status 165) 166{ 167 CODING_ERROR (status); 168 169 RPC_MUTEX_INIT (obj_mutex); 170 *status = rpc_s_ok; 171} 172 173/* 174**++ 175** 176** ROUTINE NAME: rpc__obj_fork_handler 177** 178** SCOPE: PRIVATE - declared in com.h 179** 180** DESCRIPTION: 181** 182** Initializes this module. 183** 184** INPUTS: stage The stage of the fork we are 185** currently handling. 186** 187** INPUTS/OUTPUTS: none 188** 189** OUTPUTS: none 190** 191** IMPLICIT INPUTS: none 192** 193** IMPLICIT OUTPUTS: none 194** 195** FUNCTION VALUE: void 196** 197** SIDE EFFECTS: none 198** 199**-- 200**/ 201 202PRIVATE void rpc__obj_fork_handler 203( 204 rpc_fork_stage_id_t stage 205) 206{ 207 unsigned32 i; 208 209 switch ((int)stage) 210 { 211 case RPC_C_PREFORK: 212 break; 213 case RPC_C_POSTFORK_PARENT: 214 break; 215 case RPC_C_POSTFORK_CHILD: 216 217 inq_fn = NULL; 218 219 /* 220 * Empty the Object Registry Table 221 */ 222 for (i = 0; i < RPC_C_OBJ_REGISTRY_SIZE; i++) 223 { 224 obj_registry[i].next = NULL; 225 obj_registry[i].last = NULL; 226 } 227 break; 228 } 229} 230 231 232/* 233**++ 234** 235** ROUTINE NAME: rpc_object_set_type 236** 237** SCOPE: PUBLIC - declared in rpc.idl 238** 239** DESCRIPTION: 240** 241** Register the type UUID of an object with the Common Communications 242** Service. This routine is used in conjunction with rpc_server_register_if 243** to allow a server to support multiple implementations of the same 244** interface for different object types. Registering objects is required 245** only when generic interfaces are declared (via "rpc_server_register_if"). 246** The Common Communications Service will dispatch to a specific 247** implementation, contained in a manager Entry Point Vector, based on the 248** object UUID contained in the binding of the RPC. The Common Communications 249** Service, using the results of a call to this routine, will determine 250** the type UUID of the object. A manager EPV for this type UUID can 251** then be found using the results of a call to the rpc_server_register_if 252** routine. 253** 254** INPUTS: 255** 256** object_uuid The object to be registered. 257** 258** type_uuid The type of the object. 259** 260** INPUTS/OUTPUTS: none 261** 262** OUTPUTS: 263** 264** status A value indicating the status of the routine. 265** 266** rpc_s_ok 267** rpc_s_coding_error 268** rpc_s_invalid_object 269** rpc_s_invalid_type 270** 271** IMPLICIT INPUTS: none 272** 273** IMPLICIT OUTPUTS: none 274** 275** FUNCTION VALUE: void 276** 277** SIDE EFFECTS: none 278** 279**-- 280**/ 281 282PUBLIC void rpc_object_set_type 283( 284 uuid_p_t object_uuid, 285 uuid_p_t type_uuid, 286 unsigned32 *status 287) 288{ 289 rpc_obj_rgy_entry_p_t obj_entry; 290 unsigned32 index; 291 292 CODING_ERROR (status); 293 RPC_VERIFY_INIT (); 294 295 /* 296 * check to see if this is a valid, non-null object UUIDs 297 */ 298 if (UUID_IS_NIL (object_uuid, status)) 299 { 300 *status = rpc_s_invalid_object; 301 return; 302 } 303 304 if (*status != uuid_s_ok) 305 { 306 *status = rpc_s_invalid_object; 307 return; 308 } 309 310 /* 311 * compute a hash value using the object uuid - check the status 312 * from uuid_hash to make sure the uuid has a valid format 313 */ 314 index = (uuid_hash (object_uuid, status)) % RPC_C_OBJ_REGISTRY_SIZE; 315 316 if (*status != uuid_s_ok) 317 { 318 return; 319 } 320 321 /* 322 * take out a global lock on the object registry 323 */ 324 RPC_MUTEX_LOCK (obj_mutex); 325 326 /* 327 * search the registry for a matching object 328 */ 329 RPC_LIST_FIRST (obj_registry[index], obj_entry, rpc_obj_rgy_entry_p_t); 330 331 while (obj_entry != NULL) 332 { 333 if (uuid_equal (&(obj_entry->object_uuid), object_uuid, status)) 334 { 335 break; 336 } 337 338 RPC_LIST_NEXT (obj_entry, obj_entry, rpc_obj_rgy_entry_p_t); 339 } 340 341 /* 342 * if the type UUID is the NIL UUID, remove the type entry 343 * for this object if it exists(this is basically an "unregister") 344 */ 345 if (UUID_IS_NIL(type_uuid, status)) 346 { 347 /* 348 * remove the object entry from the registry and free it 349 */ 350 if (obj_entry != NULL) 351 { 352 RPC_LIST_REMOVE (obj_registry[index], obj_entry); 353 RPC_MEM_FREE (obj_entry, RPC_C_MEM_OBJ_RGY_ENTRY); 354 } 355 } 356 else 357 { 358 /* 359 * this is a register - if no entry was found, create one 360 */ 361 if (obj_entry == NULL) 362 { 363 RPC_MEM_ALLOC ( 364 obj_entry, 365 rpc_obj_rgy_entry_p_t, 366 sizeof (rpc_obj_rgy_entry_t), 367 RPC_C_MEM_OBJ_RGY_ENTRY, 368 RPC_C_MEM_WAITOK); 369 370 /* 371 * initialize the entry 372 */ 373 obj_entry->object_uuid = *object_uuid; 374 375 /* 376 * put the object on the list for this hash index 377 */ 378 RPC_LIST_ADD_TAIL 379 (obj_registry[index], obj_entry, rpc_obj_rgy_entry_p_t); 380 } 381 else 382 { 383 /* 384 * see if the type uuid matches the one specified 385 */ 386 if (uuid_equal (&(obj_entry->type_uuid), type_uuid, status)) 387 { 388 RPC_MUTEX_UNLOCK (obj_mutex); 389 *status = rpc_s_already_registered; 390 return; 391 } 392 } 393 394 /* 395 * set the type uuid for this object entry 396 */ 397 obj_entry->type_uuid = *type_uuid; 398 } 399 400 RPC_MUTEX_UNLOCK (obj_mutex); 401 *status = rpc_s_ok; 402 return; 403} 404 405/* 406**++ 407** 408** ROUTINE NAME: rpc_object_inq_type 409** 410** SCOPE: PUBLIC - declared in rpc.idl 411** 412** DESCRIPTION: 413** 414** Consult the object registry for the specified object's type. If 415** it is not found and the application has registered an inquiry function, 416** call it. Otherwise, if object is not registered, the type returned 417** is nil_uuid. 418** 419** Note: If a NULL value is passed for the type UUID argument the routine 420** will execute, but the type UUID will not be returned. This can be 421** useful to determine if an object is registered without requiring a 422** return value to be supplied. 423** 424** INPUTS: 425** 426** object_uuid The object being looked up. 427** 428** INPUTS/OUTPUTS: none 429** 430** OUTPUTS: 431** 432** type_uuid The type of the object. 433** 434** status A value indicating the status of the routine. 435** 436** rpc_s_ok 437** rpc_s_object_not_found 438** rpc_s_coding_error 439** 440** IMPLICIT INPUTS: none 441** 442** IMPLICIT OUTPUTS: none 443** 444** FUNCTION VALUE: void 445** 446** SIDE EFFECTS: none 447** 448**-- 449**/ 450 451PUBLIC void rpc_object_inq_type 452( 453 uuid_p_t object_uuid, 454 idl_uuid_t *type_uuid, 455 unsigned32 *status 456) 457{ 458 rpc_obj_rgy_entry_p_t obj_entry; 459 unsigned32 index; 460 461 CODING_ERROR (status); 462 RPC_VERIFY_INIT (); 463 464 /* 465 * lookups on nil objects return nil types 466 */ 467 if (UUID_IS_NIL (object_uuid, status)) 468 { 469 UUID_CREATE_NIL (type_uuid); 470 *status = rpc_s_ok; 471 return; 472 } 473 474 /* 475 * compute a hash value using the object uuid - check the status 476 * from uuid_hash to make sure the uuid has a valid format 477 */ 478 index = uuid_hash (object_uuid, status) % RPC_C_OBJ_REGISTRY_SIZE; 479 480 if (*status != uuid_s_ok) 481 { 482 return; 483 } 484 485 /* 486 * take out a lock to protect access to the object registry 487 */ 488 RPC_MUTEX_LOCK (obj_mutex); 489 490 /* 491 * search the table for the specified object UUID 492 */ 493 RPC_LIST_FIRST (obj_registry[index], obj_entry, rpc_obj_rgy_entry_p_t); 494 495 while (obj_entry != NULL) 496 { 497 if (uuid_equal (&(obj_entry->object_uuid), object_uuid, status)) 498 { 499 /* 500 * if a type uuid is wanted, return it 501 */ 502 if (type_uuid != NULL) 503 { 504 *type_uuid = obj_entry->type_uuid; 505 } 506 507 RPC_MUTEX_UNLOCK (obj_mutex); 508 *status = rpc_s_ok; 509 return; 510 } 511 512 RPC_LIST_NEXT (obj_entry, obj_entry, rpc_obj_rgy_entry_p_t); 513 } 514 515 /* 516 * If there's an application function to map object to type, call it now. 517 * Ensure that a object_not_found failure returns the nil-type. 518 */ 519 if (inq_fn != NULL) 520 { 521 RPC_MUTEX_UNLOCK (obj_mutex); 522 (*inq_fn) (object_uuid, type_uuid, status); 523 if (*status == rpc_s_object_not_found) 524 { 525 UUID_CREATE_NIL (type_uuid); 526 } 527 return; 528 } 529 530 UUID_CREATE_NIL (type_uuid); 531 532 RPC_MUTEX_UNLOCK (obj_mutex); 533 *status = rpc_s_object_not_found; 534 return; 535} 536 537/* 538**++ 539** 540** ROUTINE NAME: rpc_object_set_inq_fn 541** 542** SCOPE: PUBLIC - declared in rpc.idl 543** 544** DESCRIPTION: 545** 546** Supply a function that is called by the runtime to determine the type 547** of objects that have not been set by "rpc_object_set_type". 548** 549** INPUTS: 550** 551** inq_fn function that does the inquiry 552** 553** INPUTS/OUTPUTS: none 554** 555** OUTPUTS: 556** 557** status A value indicating the status of the routine. 558** 559** IMPLICIT INPUTS: none 560** 561** IMPLICIT OUTPUTS: none 562** 563** FUNCTION VALUE: void 564** 565** SIDE EFFECTS: none 566** 567**-- 568**/ 569 570PUBLIC void rpc_object_set_inq_fn 571( 572 rpc_object_inq_fn_t inq_fn_arg, 573 unsigned32 *status 574) 575{ 576 CODING_ERROR (status); 577 RPC_VERIFY_INIT (); 578 579 inq_fn = inq_fn_arg; 580 *status = rpc_s_ok; 581} 582