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**      ctxerrtl.c
82**
83**  FACILITY:
84**
85**      IDL Stub Runtime Support
86**
87**  ABSTRACT:
88**
89**      Runtime support for caller context
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#ifdef DEBUGCTX
103#  include <stdio.h>
104#endif
105
106#ifdef PERFMON
107#include <dce/idl_log.h>
108#endif
109
110/* On the caller side a context handle is a pointer into the stub's data space.
111    The object pointed to contains a 0 attributes word, a UUID and a handle_t */
112
113/*****************************************************************************/
114/*                                                                           */
115/* Uses  malloc  to create a  context_element_t  containing the              */
116/* wire rep of the context handle and the binding handle                     */
117/*  of the association. Makes the caller's context handle point at           */
118/* the created object. Starts liveness maintenance                           */
119/*                                                                           */
120/*****************************************************************************/
121static void rpc_ss_create_caller_context
122(
123    ndr_context_handle *p_wire_context,
124              /* Pointer to the wire representation of the context_handle */
125    handle_t caller_handle,    /* Binding handle */
126    rpc_ss_context_t *p_caller_context, /* Pointer to caller's context handle */
127    error_status_t *p_st
128)
129{
130    rpc_ss_caller_context_element_t *p_created_context;
131
132#ifdef PERFMON
133    RPC_SS_CREATE_CALLER_CONTEXT_N;
134#endif
135
136    p_created_context = (rpc_ss_caller_context_element_t *)
137                       malloc(sizeof(rpc_ss_caller_context_element_t));
138    if (p_created_context == NULL)
139    {
140
141#ifdef PERFMON
142    RPC_SS_CREATE_CALLER_CONTEXT_X;
143#endif
144
145        DCETHREAD_RAISE( rpc_x_no_memory );
146        return;
147    }
148
149    p_created_context->context_on_wire.context_handle_attributes
150        = p_wire_context->context_handle_attributes;
151    memcpy(
152            (char *)&p_created_context->context_on_wire.context_handle_uuid,
153            (char *)&p_wire_context->context_handle_uuid,
154                        sizeof(idl_uuid_t));
155
156    rpc_binding_copy(caller_handle, &p_created_context->using_handle, p_st);
157    if (*p_st != error_status_ok) return;
158    *p_caller_context = (rpc_ss_context_t)p_created_context;
159    rpc_network_maintain_liveness(p_created_context->using_handle, p_st);
160#ifdef PERFMON
161    RPC_SS_CREATE_CALLER_CONTEXT_X;
162#endif
163
164}
165
166/******************************************************************************/
167/*                                                                            */
168/*    Convert wire form of context handle to local form and update the stub's */
169/*    internal tables                                                         */
170/*                                                                            */
171/******************************************************************************/
172void rpc_ss_er_ctx_from_wire
173(
174    ndr_context_handle      *p_wire_context,
175    rpc_ss_context_t        *p_caller_context, /* Pointer to application context */
176    handle_t                caller_handle,     /* Binding handle */
177    ndr_boolean             in_out,            /* TRUE for [in,out], FALSE for [out] */
178    volatile error_status_t *p_st
179)
180{
181#ifdef DEBUGCTX
182    debug_context_uuid(&p_wire_context->context_handle_uuid, "N");
183#endif
184
185#ifdef PERFMON
186    RPC_SS_ER_CTX_FROM_WIRE_N;
187#endif
188
189    if (in_out) {
190        if (
191            uuid_is_nil(
192                &p_wire_context->context_handle_uuid, (error_status_t *)p_st
193            )
194        ) {
195            /* Context is now NIL */
196            if (*p_caller_context != NULL) {
197                /* If it wasn't NIL previously, stop monitoring it */
198                rpc_network_stop_maintaining(
199                    caller_handle, (error_status_t *)p_st
200                );
201                rpc_binding_free(
202                     &((rpc_ss_caller_context_element_t *)*p_caller_context)
203                        ->using_handle, (error_status_t *)p_st
204                );
205                /* Now release it */
206                free((byte_p_t)*p_caller_context);
207                *p_caller_context = NULL;
208
209#ifdef PERFMON
210                RPC_SS_ER_CTX_FROM_WIRE_X;
211#endif
212
213                return;
214            }
215        }
216        else {  /* Returned context is not NIL */
217            if (*p_caller_context != NULL) {
218                /* And it wasn't NIL before the call */
219                if (
220                    ! uuid_equal(
221                        &p_wire_context->context_handle_uuid,
222                        &((rpc_ss_caller_context_element_t *)*p_caller_context)
223                            ->context_on_wire.context_handle_uuid,
224                        (error_status_t *)p_st
225                    )
226                )
227                    DCETHREAD_RAISE( rpc_x_ss_context_damaged );
228            }
229            else {
230                /* This is a new context */
231                rpc_ss_create_caller_context(
232                    p_wire_context, caller_handle,
233                    p_caller_context, (error_status_t *)p_st
234                );
235            }
236        }
237    }
238    else {  /* Handling an OUT parameter */
239        if (
240            uuid_is_nil(
241                &p_wire_context->context_handle_uuid, (error_status_t *)p_st
242            )
243        )
244            *p_caller_context = NULL; /* A NIL context was returned */
245        else
246            rpc_ss_create_caller_context(
247                p_wire_context, caller_handle,
248                p_caller_context, (error_status_t *)p_st
249            );
250    }
251/*
252  closedown:
253*/
254#ifdef PERFMON
255    RPC_SS_ER_CTX_FROM_WIRE_X;
256#endif
257
258    return;
259}
260
261/******************************************************************************/
262/*                                                                            */
263/*    This routine converts a caller's context handle to wire format          */
264/*    This routine is only called for an IN or IN OUT  context_t   parameter  */
265/*                                                                            */
266/******************************************************************************/
267void rpc_ss_er_ctx_to_wire
268(
269    rpc_ss_context_t   caller_context,  /* The context handle the caller is using */
270    ndr_context_handle *p_wire_context, /* Where to put data to be marshalled */
271    handle_t           assoc_handle ATTRIBUTE_UNUSED,    /* Handle on which the call will be made */
272    ndr_boolean        in_out,          /* TRUE for [in,out] param, FALSE for [in] */
273    volatile error_status_t     *p_st
274)
275{
276
277#ifdef PERFMON
278    RPC_SS_ER_CTX_TO_WIRE_N;
279#endif
280
281    *p_st = error_status_ok;
282    if (caller_context != NULL)
283    {
284        memcpy(
285         (char *)p_wire_context,
286         (char *)
287          &((rpc_ss_caller_context_element_t *)caller_context)->context_on_wire,
288             sizeof(ndr_context_handle) );
289    }
290    else
291    {
292        if ( in_out )
293        {
294            /* No active context. Send callee a NIL UUID */
295            p_wire_context->context_handle_attributes = 0;
296            uuid_create_nil(&p_wire_context->context_handle_uuid,(unsigned32*)p_st);
297        }
298        else
299        {
300            DCETHREAD_RAISE( rpc_x_ss_in_null_context );
301        }
302    }
303
304#ifdef DEBUGCTX
305    debug_context_uuid(&p_wire_context->context_handle_uuid, "L");
306#endif
307
308#ifdef PERFMON
309    RPC_SS_ER_CTX_TO_WIRE_X;
310#endif
311
312}
313
314#ifdef DEBUGCTX
315static ndr_boolean debug_file_open = ndr_false;
316static char *debug_file = "ctxer.dmp";
317static FILE *debug_fid;
318
319static int debug_context_uuid(uuid_p, prefix)
320    unsigned char *uuid_p;
321    char *prefix;
322{
323    int j;
324    unsigned long k;
325
326    if (!debug_file_open)
327    {
328        debug_fid = fopen(debug_file, "w");
329        debug_file_open = ndr_true;
330    }
331
332    fprintf(debug_fid, prefix);
333    for (j=0; j<sizeof(idl_uuid_t); j++)
334    {
335        k = *uuid_p++;
336        fprintf(debug_fid, " %02x", k);
337    }
338    fprintf(debug_fid, "\n");
339}
340#endif
341
342/******************************************************************************/
343/*                                                                            */
344/* Function to be called by user to release unusable context_handle           */
345/*                                                                            */
346/******************************************************************************/
347void rpc_ss_destroy_client_context
348(
349    rpc_ss_context_t *p_unusable_context_handle
350)
351{
352
353#ifdef PERFMON
354    RPC_SS_DESTROY_CLIENT_CONTEXT_N;
355#endif
356
357    free( *p_unusable_context_handle );
358    *p_unusable_context_handle = NULL;
359
360#ifdef PERFMON
361    RPC_SS_DESTROY_CLIENT_CONTEXT_X;
362#endif
363
364}
365