1 /*
2  * Warning - before reading this file, and while hacking
3  * it, it is advisable to examine:
4  *
5  *    docs/internals/interface-indirection.gnumeric
6  *
7  * FIXME: We need some global I/F -> m_data lookup action
8  * FIXME: We need to map interface inheritance.
9  * FIXME: Add #ifdef ORBIT_PURIFY support.
10  *
11  * FIXME: 'Obvious' optimizations
12  *  Here:
13  *    * 2 demarshalers - 1 straight, 1 endianness switching.
14  *    * do more alloca's for basic things
15  *    * more IDL compiler help for allocation and indirection
16  *    decisions - these are closely tied
17  *    * No alias types in the structures ... nice :-)
18  *  Elsewhere:
19  *    * store object profiles in GIOP format for fast marshaling
20  *    * make locking more chunky _T everything.
21  */
22 
23 #include <config.h>
24 #include <sys/types.h>
25 #ifdef HAVE_UNISTD_H
26 #  include <unistd.h>
27 #endif
28 #include <stdio.h>
29 #include <string.h>
30 
31 #include <gmodule.h>
32 #include <glib.h>
33 
34 #include <orbit/orbit.h>
35 
36 #include "../poa/orbit-poa-export.h"
37 #include "../GIOP/giop-debug.h"
38 #include "orb-core-private.h"
39 #include "orbit-debug.h"
40 
41 int ORBit_small_flags = 0;
42 
43 gpointer
ORBit_small_alloc(CORBA_TypeCode tc)44 ORBit_small_alloc (CORBA_TypeCode tc)
45 {
46 	return ORBit_alloc_by_tc (tc);
47 }
48 
49 gpointer
ORBit_small_allocbuf(CORBA_TypeCode tc,CORBA_unsigned_long length)50 ORBit_small_allocbuf (CORBA_TypeCode tc, CORBA_unsigned_long length)
51 {
52 	/* see above */
53 	return ORBit_alloc_tcval (tc->subtypes [0], length);
54 }
55 
56 void
ORBit_small_freekids(CORBA_TypeCode tc,gpointer p,gpointer d)57 ORBit_small_freekids (CORBA_TypeCode tc, gpointer p, gpointer d)
58 {
59 	/* see above */
60 	ORBit_freekids_via_TypeCode (tc, p);
61 }
62 
63 static void
ORBit_handle_exception_array(GIOPRecvBuffer * rb,CORBA_Environment * ev,const ORBit_ITypes * types,CORBA_ORB orb)64 ORBit_handle_exception_array (GIOPRecvBuffer     *rb,
65 			      CORBA_Environment  *ev,
66 			      const ORBit_ITypes *types,
67 			      CORBA_ORB           orb)
68 {
69 	CORBA_SystemException *new;
70 	CORBA_unsigned_long len, completion_status, reply_status;
71 	CORBA_char *my_repoid;
72 
73 	g_return_if_fail (rb->msg.header.message_type == GIOP_REPLY);
74 
75 	CORBA_exception_free (ev);
76 
77 	rb->cur = ALIGN_ADDRESS (rb->cur, sizeof (len));
78 	if ((rb->cur + 4) > rb->end)
79 		goto errout;
80 
81 	len = *(CORBA_unsigned_long *)rb->cur;
82 	rb->cur += 4;
83 	if (giop_msg_conversion_needed (rb))
84 		len = GUINT32_SWAP_LE_BE (len);
85 
86 	if (len) {
87 		my_repoid = (char *) rb->cur;
88 		rb->cur += len;
89 	} else
90 		my_repoid = NULL;
91 
92 	reply_status = giop_recv_buffer_reply_status (rb);
93 
94 	dprintf (MESSAGES, "Received exception %d: '%s'\n",
95 		 reply_status, my_repoid ? my_repoid : "<Null>");
96 
97 	if (reply_status == CORBA_SYSTEM_EXCEPTION) {
98 		CORBA_unsigned_long minor;
99 
100 		dprintf (MESSAGES, "system exception\n");
101 
102 		ev->_major = CORBA_SYSTEM_EXCEPTION;
103 
104 		rb->cur = ALIGN_ADDRESS (rb->cur, sizeof (minor));
105 		if ((rb->cur + sizeof (minor)) > rb->end)
106 			goto errout;
107 		minor = *(CORBA_unsigned_long *) rb->cur;
108 		rb->cur += 4;
109 		if (giop_msg_conversion_needed (rb))
110 			minor = GUINT32_SWAP_LE_BE (minor);
111 
112 		rb->cur = ALIGN_ADDRESS (rb->cur, sizeof (completion_status));
113 		if ((rb->cur + sizeof (completion_status)) > rb->end)
114 			goto errout;
115 		completion_status = *(CORBA_unsigned_long *) rb->cur;
116 		rb->cur += 4;
117 		if (giop_msg_conversion_needed (rb))
118 			completion_status = GUINT32_SWAP_LE_BE (completion_status);
119 
120 		new = CORBA_SystemException__alloc ();
121 		new->minor = minor;
122 		new->completed = completion_status;
123 
124 		/* FIXME: check what should the repo ID be? */
125 		CORBA_exception_set (ev, CORBA_SYSTEM_EXCEPTION,
126 				     my_repoid, new);
127 		/* FIXME: might be fixed one day by cunning detection
128 		   in CORBA_exception_set ... */
129 		if (!ev->_any._type)
130 			ev->_any._type = ORBit_RootObject_duplicate (
131 				TC_CORBA_SystemException);
132 
133 		dprintf (MESSAGES, "system exception de-marshaled\n");
134 		return;
135 
136 	} else if (reply_status == CORBA_USER_EXCEPTION) {
137 		int i;
138 
139 		dprintf (MESSAGES, "user exception\n");
140 
141 		for (i = 0; my_repoid && i < types->_length; i++) {
142 			if (!strcmp (types->_buffer[i]->repo_id, my_repoid))
143 				break;
144 		}
145 
146 		if (!types || types->_length == 0 || i >= types->_length) {
147 			/* weirdness; they raised an exception that we don't
148 			   know about */
149 			CORBA_exception_set_system (
150 				ev, ex_CORBA_MARSHAL,
151 				CORBA_COMPLETED_MAYBE);
152 		} else {
153 			gpointer data;
154 
155 			dprintf (MESSAGES, "de-marshal user exception\n");
156 
157 			data = ORBit_demarshal_arg (
158 				rb, types->_buffer [i], orb);
159 
160 			/* FIXME: might be fixed one day by cunning detection
161 			   in CORBA_exception_set ... */
162 			CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
163 					     types->_buffer [i]->repo_id, data);
164 			if (!ev->_any._type)
165 				ev->_any._type = ORBit_RootObject_duplicate (
166 					types->_buffer [i]);
167 		}
168 	}
169 
170 	if (ev->_major != CORBA_NO_EXCEPTION)
171 		return;
172 
173  errout:
174 	/* ignore LOCATION_FORWARD here, that gets handled in the stub */
175 	CORBA_exception_set_system (ev, ex_CORBA_MARSHAL,
176 				    CORBA_COMPLETED_MAYBE);
177 }
178 
179 static gboolean
ORBit_small_send_user_exception(GIOPSendBuffer * send_buffer,CORBA_Environment * ev,const ORBit_ITypes * types)180 ORBit_small_send_user_exception (GIOPSendBuffer     *send_buffer,
181 				 CORBA_Environment  *ev,
182 				 const ORBit_ITypes *types)
183 {
184 	int i;
185 
186 	for (i = 0; i < types->_length; i++) {
187 		if(!strcmp (types->_buffer[i]->repo_id, ev->_id))
188 			break;
189 	}
190 
191 	if (i >= types->_length) {
192 		g_warning ("Some clown returned undeclared "
193 			   "exception '%s' ", ev->_id);
194 
195 		CORBA_exception_free (ev);
196 		CORBA_exception_set_system (
197 			ev, ex_CORBA_UNKNOWN,
198 			CORBA_COMPLETED_MAYBE);
199 
200 		giop_send_buffer_unuse (send_buffer);
201 
202 		return FALSE;
203 	} else {
204 		giop_send_buffer_append_string (send_buffer, ev->_id);
205 
206 		dprintf (MESSAGES, "Returning exception of type '%s'\n", ev->_id);
207 
208 		ORBit_marshal_arg (send_buffer, ev->_any._value,
209 				   types->_buffer[i]);
210 
211 		return TRUE;
212 	}
213 }
214 
215 static void
ORBit_small_marshal_context(GIOPSendBuffer * send_buffer,ORBit_IMethod * m_data,CORBA_Context ctx)216 ORBit_small_marshal_context (GIOPSendBuffer *send_buffer,
217 			     ORBit_IMethod  *m_data,
218 			     CORBA_Context   ctx)
219 {
220 	int i;
221 	/* Horrible inefficiency to get round the 'lete
222 	   efficiency of the current impl */
223 	ORBit_ContextMarshalItem *mlist;
224 
225 	mlist = g_alloca (sizeof (ORBit_ContextMarshalItem) *
226 			m_data->contexts._length);
227 
228 	tprintf (" context { ");
229 
230 	for (i = 0; i < m_data->contexts._length; i++) {
231 		char *val;
232 
233 		mlist [i].str = m_data->contexts._buffer [i];
234 
235 		val = g_hash_table_lookup (ctx->mappings, mlist [i].str);
236 		tprintf ("( %s: '%s' )%s", mlist [i].str, val,
237 			 i < m_data->contexts._length - 1 ? ", ": "");
238 
239 		mlist [i].len = strlen (mlist [i].str) + 1;
240 	}
241 
242 	tprintf (" }");
243 
244 	/* Assumption, this doesn't whack mlist pointers into
245 	   the send_buffer: verified */
246 	ORBit_Context_marshal (
247 		ctx, mlist, m_data->contexts._length, send_buffer);
248 }
249 
250 #define BASE_TYPES \
251 	     CORBA_tk_short: \
252 	case CORBA_tk_long: \
253 	case CORBA_tk_enum: \
254 	case CORBA_tk_ushort: \
255 	case CORBA_tk_ulong: \
256 	case CORBA_tk_float: \
257 	case CORBA_tk_double: \
258 	case CORBA_tk_boolean: \
259 	case CORBA_tk_char: \
260 	case CORBA_tk_octet: \
261 	case CORBA_tk_longlong: \
262 	case CORBA_tk_ulonglong: \
263 	case CORBA_tk_longdouble: \
264 	case CORBA_tk_wchar
265 
266 #define STRUCT_UNION_TYPES \
267 	     CORBA_tk_struct: \
268 	case CORBA_tk_union: \
269 	case CORBA_tk_except
270 
271 #define OBJ_STRING_TYPES \
272 	     CORBA_tk_objref: \
273 	case CORBA_tk_TypeCode: \
274 	case CORBA_tk_string: \
275 	case CORBA_tk_wstring
276 
277 #define SEQ_ANY_TYPES \
278 	     CORBA_tk_sequence: \
279 	case CORBA_tk_any
280 
281 typedef struct {
282 	CORBA_unsigned_long len;
283 	char                opname[1];
284 } OpData;
285 
286 #define do_marshal_value(a,b,c)     \
287 	ORBit_marshal_value   ((a),(gconstpointer *)(b),(c))
288 #define do_demarshal_value(a,b,c,e) \
289 	if (ORBit_demarshal_value ((c),(b),(a),(e))) \
290 		goto demarshal_exception
291 
292 static gboolean
orbit_small_marshal(CORBA_Object obj,GIOPConnection * cnx,GIOPMessageQueueEntry * mqe,CORBA_unsigned_long request_id,ORBit_IMethod * m_data,gpointer * args,CORBA_Context ctx)293 orbit_small_marshal (CORBA_Object           obj,
294 		     GIOPConnection        *cnx,
295 		     GIOPMessageQueueEntry *mqe,
296 		     CORBA_unsigned_long    request_id,
297 		     ORBit_IMethod         *m_data,
298 		     gpointer              *args,
299 		     CORBA_Context          ctx)
300 {
301 	GIOPSendBuffer          *send_buffer;
302 	struct iovec             op_vec;
303 	CORBA_TypeCode           tc;
304 	int                      i;
305 
306 	tprintf_header (obj, m_data);
307 
308 	{
309 		int          align;
310 		int          len = sizeof (CORBA_unsigned_long) + m_data->name_len + 1;
311 		guchar      *header = g_alloca (len + sizeof (CORBA_unsigned_long));
312 
313 		*(CORBA_unsigned_long *) header = m_data->name_len + 1;
314 		memcpy (header + sizeof (CORBA_unsigned_long),
315 			m_data->name, m_data->name_len + 1);
316 
317 		align = len + (sizeof (CORBA_unsigned_long) - 1);
318 		align &= ~(sizeof (CORBA_unsigned_long) - 1);
319 		memset (header + len, 0, align - len);
320 
321 		dprintf (MESSAGES, "Align = %d\n", align);
322 		op_vec.iov_len  = align;
323 		op_vec.iov_base = header;
324 	}
325 
326 	send_buffer = giop_send_buffer_use_request (
327 		cnx->giop_version, request_id,
328 		(m_data->flags & ORBit_I_METHOD_1_WAY) == 0,
329 		obj->object_key, &op_vec, NULL);
330 
331 	if (!send_buffer)
332 		return FALSE;
333 
334 	dprintf (MESSAGES, "Marshal: id 0x%x\n", request_id);
335 
336 	for (i = 0; i < m_data->arguments._length; i++) {
337 
338 		ORBit_IArg *a = &m_data->arguments._buffer [i];
339 		gpointer    p;
340 
341 		if (!(a->flags & (ORBit_I_ARG_IN |
342 				  ORBit_I_ARG_INOUT)))
343 			continue;
344 		tc = a->tc;
345 
346 		while (tc->kind == CORBA_tk_alias)
347 			tc = tc->subtypes [0];
348 
349 		dump_arg (a, tc);
350 
351 		p = args [i];
352 		tprintf_trace_value (&p, tc);
353 
354 		p = args [i];
355 		do_marshal_value (send_buffer, &p, tc);
356 
357 		if (i < m_data->arguments._length - 1)
358 			tprintf (", ");
359 	}
360 
361 	tprintf (")");
362 
363 	if (m_data->contexts._length > 0)
364 		ORBit_small_marshal_context (send_buffer, m_data, ctx);
365 
366 	do_giop_dump_send (send_buffer);
367 
368 	if (giop_send_buffer_write (send_buffer, cnx, FALSE)) {
369 		g_warning ("Failed to send buffer");
370 		giop_recv_list_destroy_queue_entry (mqe);
371 		return FALSE;
372 	}
373 
374 	giop_send_buffer_unuse (send_buffer);
375 
376 	return TRUE;
377 }
378 
379 typedef enum {
380 	MARSHAL_SYS_EXCEPTION_INCOMPLETE,
381 	MARSHAL_SYS_EXCEPTION_COMPLETE,
382 	MARSHAL_EXCEPTION_COMPLETE,
383 	MARSHAL_RETRY,
384 	MARSHAL_CLEAN
385 } DeMarshalRetType;
386 
387 static DeMarshalRetType
orbit_small_demarshal(CORBA_Object obj,GIOPConnection ** cnx,GIOPRecvBuffer * recv_buffer,CORBA_Environment * ev,gpointer ret,ORBit_IMethod * m_data,gpointer * args)388 orbit_small_demarshal (CORBA_Object           obj,
389 		       GIOPConnection       **cnx,
390 		       GIOPRecvBuffer        *recv_buffer,
391 		       CORBA_Environment     *ev,
392 		       gpointer               ret,
393 		       ORBit_IMethod         *m_data,
394 		       gpointer              *args)
395 {
396 	gpointer        data, p;
397 	CORBA_TypeCode  tc;
398 	CORBA_ORB       orb = obj->orb;
399 
400 	if (!recv_buffer) {
401 		dprintf (MESSAGES, "No recv buffer ...\n");
402 		return MARSHAL_SYS_EXCEPTION_INCOMPLETE;
403 	}
404 
405 	if (giop_recv_buffer_reply_status (recv_buffer) != GIOP_NO_EXCEPTION)
406  		goto msg_exception;
407 
408 	if ((tc = m_data->ret) && tc->kind != CORBA_tk_void) {
409 		tprintf (" =>: ");
410 
411 		g_assert (ret != NULL);
412 
413 		while (tc->kind == CORBA_tk_alias)
414 			tc = tc->subtypes [0];
415 
416 		switch (tc->kind) {
417 		case BASE_TYPES:
418 		case OBJ_STRING_TYPES:
419 			p = ret;
420 			do_demarshal_value (recv_buffer, &ret, tc, orb);
421 			tprintf_trace_value (&p, tc);
422 			break;
423 
424 		case STRUCT_UNION_TYPES:
425 			if (m_data->flags & ORBit_I_COMMON_FIXED_SIZE) {
426 				p = ret;
427 				do_demarshal_value (recv_buffer, &ret, tc, orb);
428 				tprintf_trace_value (&p, tc);
429 				break;
430 			} /* drop through */
431 
432 		case SEQ_ANY_TYPES:
433 		case CORBA_tk_array:
434 		default:
435 			data = ORBit_demarshal_arg (recv_buffer, tc, orb);
436 			if (!data)
437 				return MARSHAL_SYS_EXCEPTION_COMPLETE;
438 
439 			p = data;
440 			tprintf_trace_value (&p, tc);
441 
442 			*((gpointer *)ret) = data;
443 			break;
444 		}
445 	}
446 
447 	{
448 		int i;
449 		int trace_have_out = 0;
450 
451 		for (i = 0; i < m_data->arguments._length; i++) {
452 			const ORBit_IArg *a;
453 			gpointer          arg;
454 
455 			a = &m_data->arguments._buffer [i];
456 
457 			if (!(a->flags & (ORBit_I_ARG_OUT |
458 					  ORBit_I_ARG_INOUT)))
459 				continue;
460 
461 			tc = a->tc;
462 
463 			while (tc->kind == CORBA_tk_alias)
464 				tc = tc->subtypes [0];
465 
466 			dump_arg (a, tc);
467 
468 			if (a->flags & ORBit_I_ARG_OUT)
469 				/* this may read (&discard) uninitialized memory,
470 				 * see 'foo' below. This is for simplicity. */
471 				arg = *(gpointer *)args [i];
472 			else
473 				arg = args [i];
474 
475 			switch (tc->kind) {
476 			case OBJ_STRING_TYPES: {
477 				if (a->flags & ORBit_I_ARG_INOUT) {
478 					if (tc->kind == CORBA_tk_TypeCode ||
479 					    tc->kind == CORBA_tk_objref)
480 						CORBA_Object_release (*(gpointer *)arg, ev);
481 					else if (tc->kind == CORBA_tk_string ||
482 						 tc->kind == CORBA_tk_wstring)
483 						ORBit_free (*(gpointer *) arg);
484 				}
485 				/* drop through */
486 			case BASE_TYPES:
487 				if (!trace_have_out++)
488 					tprintf (" out: (");
489 				p = arg;
490 				do_demarshal_value (recv_buffer, &arg, tc, orb);
491 				tprintf_trace_value (&p, tc);
492 				break;
493 			}
494 
495 			case STRUCT_UNION_TYPES:
496 			case SEQ_ANY_TYPES:
497 			case CORBA_tk_array:
498 			default:
499 				p = arg;
500 				if (a->flags & ORBit_I_COMMON_FIXED_SIZE) {
501 					do_demarshal_value (recv_buffer, &arg, tc, orb);
502 				} else if (a->flags & ORBit_I_ARG_INOUT) {
503 					ORBit_freekids_via_TypeCode (tc, arg);
504 					do_demarshal_value (recv_buffer, &arg, tc, orb);
505 				} else /* 'foo' - don't use the bogus 'arg' contents */
506 					*(gpointer *)args [i] = p = ORBit_demarshal_arg (
507 						recv_buffer, tc, obj->orb);
508 
509 				if (!trace_have_out++)
510 					tprintf (" out: (");
511 				tprintf_trace_value (&p, tc);
512 				break;
513 			}
514 			if (trace_have_out &&
515 			    i < m_data->arguments._length - 1)
516 				tprintf (", ");
517 		}
518 		if (trace_have_out)
519 			tprintf (" )");
520 	}
521 
522 	return MARSHAL_CLEAN;
523 
524  demarshal_exception:
525 	/* FIXME: may well leak */
526 	CORBA_exception_set_system(ev, ex_CORBA_MARSHAL,
527 				   CORBA_COMPLETED_MAYBE);
528 	return MARSHAL_EXCEPTION_COMPLETE;
529 
530  msg_exception:
531 	if (giop_recv_buffer_reply_status (recv_buffer) ==
532 	    GIOP_LOCATION_FORWARD) {
533 
534 		*cnx = ORBit_handle_location_forward (recv_buffer, obj);
535 		tprintf (" Exception: forward (%p)", *cnx);
536 		if (!*cnx) {
537 			CORBA_exception_set_system(ev, ex_CORBA_MARSHAL,
538 						   CORBA_COMPLETED_MAYBE);
539 			return MARSHAL_SYS_EXCEPTION_INCOMPLETE;
540 		}
541 		return MARSHAL_RETRY;
542 	} else {
543 		ORBit_handle_exception_array (
544 			recv_buffer, ev, &m_data->exceptions, obj->orb);
545 
546 #ifdef G_ENABLE_DEBUG
547 		if (_orbit_debug_flags & ORBIT_DEBUG_TRACES) {
548 			if (ev->_major == CORBA_SYSTEM_EXCEPTION)
549 				tprintf (" System Exception: '%s' ", ev->_id);
550 			else {
551 				tprintf (" User Exception: '%s' ", ev->_id);
552 				ORBit_trace_any (&ev->_any);
553 			}
554 		}
555 #endif /* G_ENABLE_DEBUG */
556 
557 		return MARSHAL_EXCEPTION_COMPLETE;
558 	}
559 }
560 
561 void
ORBit_small_invoke_stub_n(CORBA_Object object,ORBit_IMethods * methods,glong index,gpointer ret,gpointer * args,CORBA_Context ctx,CORBA_Environment * ev)562 ORBit_small_invoke_stub_n (CORBA_Object        object,
563 			   ORBit_IMethods     *methods,
564 			   glong               index,
565 			   gpointer            ret,
566 			   gpointer           *args,
567 			   CORBA_Context       ctx,
568 			   CORBA_Environment  *ev)
569 {
570 	if (index < 0 || index > methods->_length) {
571 		dprintf (MESSAGES, "Cannot invoke OOB method (%ld,%lu)\n",
572 			 index, (gulong)methods->_length);
573 		CORBA_exception_set_system (ev, ex_CORBA_NO_IMPLEMENT,
574 					    CORBA_COMPLETED_NO);
575 
576 	} else
577 		ORBit_small_invoke_stub (object, &methods->_buffer[index], ret, args, ctx, ev);
578 }
579 
580 void
ORBit_small_invoke_stub(CORBA_Object obj,ORBit_IMethod * m_data,gpointer ret,gpointer * args,CORBA_Context ctx,CORBA_Environment * ev)581 ORBit_small_invoke_stub (CORBA_Object       obj,
582 			 ORBit_IMethod     *m_data,
583 			 gpointer           ret,
584 			 gpointer          *args,
585 			 CORBA_Context      ctx,
586 			 CORBA_Environment *ev)
587 {
588 	CORBA_unsigned_long     request_id;
589 	CORBA_completion_status completion_status;
590 	GIOPConnection         *cnx = NULL;
591 	GIOPMessageQueueEntry   mqe;
592 	ORBit_OAObject          adaptor_obj;
593 	GIOPRecvBuffer         *recv_buffer = NULL;
594 	CORBA_Object            xt_proxy = CORBA_OBJECT_NIL;
595 	ORBitPolicy            *invoke_policy = CORBA_OBJECT_NIL;
596 	gboolean                timeout = FALSE;
597 
598 	CORBA_exception_init (ev);
599 
600 	if (!obj) {
601 		dprintf (MESSAGES, "Cannot invoke method on null object\n");
602 		CORBA_exception_set_system (ev, ex_CORBA_INV_OBJREF,
603 					    CORBA_COMPLETED_NO);
604 		goto clean_out;
605 	}
606 
607 	if ((invoke_policy = ORBit_object_get_policy (obj)))
608 		ORBit_policy_push (invoke_policy);
609 
610 	adaptor_obj = obj->adaptor_obj;
611 
612 	if (adaptor_obj) {
613 		/* FIXME: unchecked cast */
614 		if (ORBit_poa_allow_cross_thread_call ((ORBit_POAObject) adaptor_obj,
615 						       m_data->flags)) {
616 			tprintf_header (obj, m_data);
617 			tprintf ("[in-proc]");
618 			ORBit_small_handle_request (adaptor_obj, m_data->name, ret,
619 						    args, ctx, NULL, ev);
620 			goto clean_out;
621 		} else {
622 			tprintf ("[in-proc-XT]");
623 			/*
624 			 * FIXME: this is _really_ slow, can easily be optimised
625 			 * by shoving the GIOP data straight on the incoming
626 			 * queue
627 			 */
628 			xt_proxy = ORBit_objref_get_proxy (obj);
629 			obj = xt_proxy;
630 		}
631 	} else
632 		giop_thread_new_check (NULL);
633 
634 	cnx = ORBit_object_get_connection (obj);
635 
636 	if (!cnx) {
637 		dprintf (MESSAGES, "Null connection on object '%p'\n", obj);
638 		completion_status = CORBA_COMPLETED_NO;
639 		goto system_exception;
640 	}
641 
642  retry_request:
643 	request_id = GPOINTER_TO_UINT (&obj);
644 	completion_status = CORBA_COMPLETED_NO;
645 
646 	giop_recv_list_setup_queue_entry (&mqe, cnx, GIOP_REPLY, request_id);
647 
648 	if (!orbit_small_marshal (obj, cnx, &mqe, request_id,
649 				  m_data, args, ctx))
650 		goto system_exception;
651 
652 	completion_status = CORBA_COMPLETED_MAYBE;
653 
654 	if (m_data->flags & ORBit_I_METHOD_1_WAY) {
655 		tprintf ("[ one way ]");
656 		giop_recv_list_destroy_queue_entry (&mqe);
657 		goto clean_out;
658 	}
659 
660 	recv_buffer = giop_recv_buffer_get (&mqe, &timeout);
661 	if (timeout)
662 		goto timeout_exception;
663 
664 	switch (orbit_small_demarshal (obj, &cnx, recv_buffer, ev,
665 				       ret, m_data, args))
666 	{
667 	case MARSHAL_SYS_EXCEPTION_COMPLETE:
668 		completion_status = CORBA_COMPLETED_YES;
669 		dprintf (MESSAGES, "Sys exception completed on id 0x%x\n\n", request_id);
670 		goto system_exception;
671 
672 	case MARSHAL_SYS_EXCEPTION_INCOMPLETE:
673 		dprintf (MESSAGES, "Sys exception incomplete on id 0x%x\n\n", request_id);
674 		goto system_exception;
675 
676 	case MARSHAL_EXCEPTION_COMPLETE:
677 		dprintf (MESSAGES, "Clean demarshal of exception on id 0x%x\n\n", request_id);
678 		break;
679 
680 	case MARSHAL_RETRY:
681 		dprintf (MESSAGES, "Retry demarshal on id 0x%x\n\n", request_id);
682 		goto retry_request;
683 
684 	case MARSHAL_CLEAN:
685 		dprintf (MESSAGES, "Clean demarshal on id 0x%x\n\n", request_id);
686 		break;
687 	};
688 
689  clean_out:
690 	ORBit_RootObject_release (xt_proxy);
691 	giop_recv_buffer_unuse (recv_buffer);
692 
693 	tprintf_end_method ();
694 	if (cnx)
695 		giop_connection_unref (cnx);
696 	if (invoke_policy) {
697 		ORBit_policy_pop ();
698 		ORBit_policy_unref (invoke_policy);
699 	}
700 	return;
701 
702  system_exception:
703 	tprintf ("[System exception comm failure] )");
704 	CORBA_exception_set_system (ev, ex_CORBA_COMM_FAILURE,
705 				    completion_status);
706 	goto clean_out;
707 
708  timeout_exception:
709 	tprintf ("[System exception timeout] )");
710 	CORBA_exception_set_system (ev, ex_CORBA_TIMEOUT,
711 				    CORBA_COMPLETED_NO);
712 	goto clean_out;
713 }
714 
715 void
ORBit_small_invoke_adaptor(ORBit_OAObject adaptor_obj,GIOPRecvBuffer * recv_buffer,ORBit_IMethod * m_data,gpointer data,CORBA_Environment * ev)716 ORBit_small_invoke_adaptor (ORBit_OAObject     adaptor_obj,
717 			    GIOPRecvBuffer    *recv_buffer,
718 			    ORBit_IMethod     *m_data,
719 			    gpointer           data,
720 			    CORBA_Environment *ev)
721 {
722 	struct CORBA_Context_type  ctx;
723 	gpointer                  *args = NULL;
724 	gpointer                  *scratch = NULL;
725 	gpointer                   pretval = NULL;
726 	gpointer                   retval = NULL;
727 	GIOPSendBuffer            *send_buffer;
728 	CORBA_ORB                  orb;
729 	CORBA_TypeCode             tc;
730 	gboolean                   has_context;
731 	int                        i;
732 
733 	orb = ((ORBit_POAObject)adaptor_obj)->poa->orb;
734 
735 	has_context = (m_data->contexts._length > 0);
736 
737 	tprintf_header (adaptor_obj->objref, m_data);
738 
739 	if ((tc = m_data->ret) && tc->kind != CORBA_tk_void) {
740 
741 		while (tc->kind == CORBA_tk_alias)
742 			tc = tc->subtypes [0];
743 
744 		switch (tc->kind) {
745 		case BASE_TYPES:
746 		case OBJ_STRING_TYPES:
747 			retval = g_alloca (ORBit_gather_alloc_info (tc));
748 			break;
749 		case STRUCT_UNION_TYPES:
750 			if (m_data->flags & ORBit_I_COMMON_FIXED_SIZE) {
751 				retval = ORBit_alloc_by_tc (tc);
752 				break;
753 			} /* drop through */
754 		default:
755 			retval = &pretval;
756 			pretval = NULL;
757 			break;
758 		}
759 	}
760 
761 	if (m_data->arguments._length > 0) {
762 		int len = m_data->arguments._length *
763 			sizeof (gpointer);
764 
765 		args = g_alloca (len);
766 		memset (args, 0, len);
767 		scratch = g_alloca (len);
768 		memset (scratch, 0, len);
769 	}
770 
771 	for (i = 0; i < m_data->arguments._length; i++) {
772 		ORBit_IArg *a = &m_data->arguments._buffer [i];
773 
774 		if (a->flags & ORBit_I_ARG_IN ||
775 		    a->flags & ORBit_I_ARG_INOUT) {
776 			gpointer p;
777 
778 			tc = a->tc;
779 
780 			while (tc->kind == CORBA_tk_alias)
781 				tc = tc->subtypes [0];
782 
783 			switch (tc->kind) {
784 			case BASE_TYPES:
785 			case OBJ_STRING_TYPES:
786 				p = args [i] = g_alloca (ORBit_gather_alloc_info (tc));
787 				do_demarshal_value (recv_buffer, &p, tc, orb);
788 
789 				p = args [i];
790 				tprintf_trace_value (&p, tc);
791 				break;
792 			case STRUCT_UNION_TYPES:
793 			case CORBA_tk_array:
794 				if (a->flags & ORBit_I_COMMON_FIXED_SIZE) {
795 					p = args [i] = g_alloca (ORBit_gather_alloc_info (tc));
796 					do_demarshal_value (recv_buffer, &p, tc, orb);
797 					p = args [i];
798 					tprintf_trace_value (&p, tc);
799 					break;
800 				} /* drop through */
801 			default:
802 				args [i] = ORBit_demarshal_arg (recv_buffer, a->tc, orb);
803 				p = args [i];
804 				tprintf_trace_value (&p, tc);
805 				break;
806 			}
807 
808 		} else { /* Out */
809 			tc = a->tc;
810 
811 			while (tc->kind == CORBA_tk_alias)
812 				tc = tc->subtypes [0];
813 
814 			args [i] = &scratch [i];
815 
816 			switch (tc->kind) {
817 			case BASE_TYPES:
818 			case OBJ_STRING_TYPES:
819 				scratch [i] = g_alloca (ORBit_gather_alloc_info (tc));
820 				break;
821 			case STRUCT_UNION_TYPES:
822 			case CORBA_tk_array:
823 				if (a->flags & ORBit_I_COMMON_FIXED_SIZE) {
824 					scratch [i] = ORBit_alloc_by_tc (tc);
825 					break;
826 				} /* drop through */
827 			default:
828 				scratch [i] = NULL;
829 				break;
830 			}
831 
832 		}
833 
834 		if (i < m_data->arguments._length - 1)
835 			tprintf (", ");
836 	}
837 
838 	tprintf (")");
839 
840 	if (has_context) {
841 		tprintf ("[FIXME:context]");
842 		if (ORBit_Context_demarshal (NULL, &ctx, recv_buffer))
843 			g_warning ("FIXME: handle context demarshaling failure");
844 	}
845 
846 	ORBit_OAObject_invoke (adaptor_obj, retval, args, &ctx, data, ev);
847 
848 	if (has_context)
849 		ORBit_Context_server_free (&ctx);
850 
851 	if (m_data->flags & ORBit_I_METHOD_1_WAY)
852 		goto clean_out;
853 	else
854 		goto handle_possible_exception;
855 
856  demarshal_exception:
857 	CORBA_exception_set_system (ev, ex_CORBA_MARSHAL,
858 				    CORBA_COMPLETED_NO);
859 
860  handle_possible_exception:
861 	/* FIXME: should we be using the connection's GIOP version ? */
862 	send_buffer = giop_send_buffer_use_reply (
863 		recv_buffer->giop_version,
864 		giop_recv_buffer_get_request_id (recv_buffer),
865 		ev->_major);
866 
867 	if (!send_buffer) {
868 		dprintf (MESSAGES, "Weird, no send_buffer");
869 		return;
870 
871 	} else if (ev->_major == CORBA_USER_EXCEPTION) {
872 		if (!ORBit_small_send_user_exception (
873 			send_buffer, ev, &m_data->exceptions)) {
874 			/* Tried to marshal an unknown exception,
875 			   so we throw a system exception next */
876 			dprintf (MESSAGES, "Re-sending an exception, this time %d: '%s'",
877 				 ev->_major, ev->_id);
878 			goto handle_possible_exception;
879 		}
880 		tprintf ("User exception '%s'", ev->_id);
881 
882 	} else if (ev->_major != CORBA_NO_EXCEPTION) {
883 		ORBit_send_system_exception (send_buffer, ev);
884 
885 		tprintf ("System exception");
886 
887 	} else { /* Marshal return values */
888 		int trace_have_out = 0;
889 
890 		if ((tc = m_data->ret) && tc->kind != CORBA_tk_void) {
891 			gpointer p = retval;
892 
893 			tprintf (" =>; ");
894 
895 			while (tc->kind == CORBA_tk_alias)
896 				tc = tc->subtypes [0];
897 
898 			switch (tc->kind) {
899 
900 			case BASE_TYPES:
901 			case OBJ_STRING_TYPES:
902 				ORBit_marshal_arg (send_buffer, retval, m_data->ret);
903 				tprintf_trace_value (&p, tc);
904 				break;
905 
906 			case STRUCT_UNION_TYPES:
907 				if (m_data->flags & ORBit_I_COMMON_FIXED_SIZE) {
908 					ORBit_marshal_arg (send_buffer, retval, m_data->ret);
909 					tprintf_trace_value (&p, tc);
910 					break;
911 				} /* drop through */
912 
913 			case CORBA_tk_any:
914 			case CORBA_tk_sequence:
915 			case CORBA_tk_array:
916 			default:
917 				p = *(gpointer *) retval;
918 				ORBit_marshal_arg (send_buffer, *(gpointer *)retval, m_data->ret);
919 				tprintf_trace_value (&p, tc);
920 				break;
921 			}
922 		}
923 
924 		for (i = 0; i < m_data->arguments._length; i++) {
925 			ORBit_IArg *a = &m_data->arguments._buffer [i];
926 			gpointer    p;
927 
928 			tc = a->tc;
929 			while (tc->kind == CORBA_tk_alias)
930 				tc = tc->subtypes [0];
931 
932 			if (a->flags & ORBit_I_ARG_INOUT) {
933 				if (!trace_have_out++)
934 					tprintf (" out: (");
935 
936 				ORBit_marshal_arg (send_buffer, args [i], tc);
937 				p = args [i];
938 				tprintf_trace_value (&p, tc);
939 			}
940 
941 			else if (a->flags & ORBit_I_ARG_OUT) {
942 				if (!trace_have_out++)
943 					tprintf (" out: (");
944 
945 				ORBit_marshal_arg (send_buffer, scratch [i], tc);
946 
947 				p = scratch [i];
948 				tprintf_trace_value (&p, tc);
949 			}
950 
951 			if (trace_have_out &&
952 			    i < m_data->arguments._length - 1 &&
953 			    m_data->arguments._buffer [i + 1].flags &
954 			    (ORBit_I_ARG_OUT | ORBit_I_ARG_INOUT))
955 				tprintf (", ");
956 		}
957 		if (trace_have_out)
958 			tprintf (" )");
959 	}
960 
961 	do_giop_dump_send (send_buffer);
962 
963 	giop_send_buffer_write (send_buffer, recv_buffer->connection, FALSE);
964 	giop_send_buffer_unuse (send_buffer);
965 
966 	if (m_data->ret && tc->kind != CORBA_tk_void) {
967 		switch (m_data->ret->kind) {
968 		case BASE_TYPES:
969 			break;
970 		case CORBA_tk_objref:
971 		case CORBA_tk_TypeCode:
972 			if (ev->_major == CORBA_NO_EXCEPTION)
973 				CORBA_Object_release (*(CORBA_Object *) retval, ev);
974 			break;
975 		case CORBA_tk_string:
976 		case CORBA_tk_wstring:
977 			if (ev->_major == CORBA_NO_EXCEPTION)
978 				ORBit_free (*(char **) retval);
979 			break;
980 		case STRUCT_UNION_TYPES:
981 			if (m_data->flags & ORBit_I_COMMON_FIXED_SIZE) {
982 				ORBit_free (retval);
983 				break;
984 			} /* drop through */
985 		default:
986 			if (ev->_major == CORBA_NO_EXCEPTION)
987 				ORBit_free (pretval);
988 			break;
989 		}
990 	}
991 
992  clean_out:
993 	tprintf_end_method ();
994 
995 	for (i = 0; i < m_data->arguments._length; i++) {
996 		ORBit_IArg *a = &m_data->arguments._buffer [i];
997 
998 		tc = a->tc;
999 
1000 		while (tc->kind == CORBA_tk_alias)
1001 			tc = tc->subtypes [0];
1002 
1003 		if (a->flags & ORBit_I_ARG_IN ||
1004 		    a->flags & ORBit_I_ARG_INOUT) {
1005 
1006 			switch (tc->kind) {
1007 			case BASE_TYPES:
1008 				break;
1009 			case CORBA_tk_objref:
1010 			case CORBA_tk_TypeCode:
1011 				CORBA_Object_release (*(CORBA_Object *) args [i], ev);
1012 				break;
1013 			case CORBA_tk_string:
1014 			case CORBA_tk_wstring:
1015 				ORBit_free (*(char **) args [i]);
1016 				break;
1017 			case STRUCT_UNION_TYPES:
1018 			case CORBA_tk_array:
1019 				if (a->flags & ORBit_I_COMMON_FIXED_SIZE) {
1020 					ORBit_freekids_via_TypeCode (tc, args [i]);
1021 					break;
1022 				}
1023 				/* drop through */
1024 			default:
1025 				ORBit_free (args [i]);
1026 				break;
1027 			}
1028 		} else { /* Out */
1029 			switch (tc->kind) {
1030 			case BASE_TYPES:
1031 				break;
1032 			case CORBA_tk_objref:
1033 			case CORBA_tk_TypeCode:
1034 				if (ev->_major == CORBA_NO_EXCEPTION)
1035 					CORBA_Object_release (*(CORBA_Object *) scratch [i], ev);
1036 				break;
1037 			case CORBA_tk_string:
1038 			case CORBA_tk_wstring:
1039 				if (ev->_major == CORBA_NO_EXCEPTION)
1040 					ORBit_free (*(char **) scratch [i]);
1041 				break;
1042 			case STRUCT_UNION_TYPES:
1043 			case CORBA_tk_array:
1044 				if (a->flags & ORBit_I_COMMON_FIXED_SIZE) {
1045 					ORBit_free (scratch [i]);
1046 					break;
1047 				}
1048 				/* drop through */
1049 			default:
1050 				if (ev->_major == CORBA_NO_EXCEPTION)
1051 					ORBit_free (scratch [i]);
1052 				break;
1053 			}
1054 		}
1055 	}
1056 
1057 	CORBA_exception_free (ev);
1058 }
1059 
1060 #ifdef DEBUG
1061 gpointer
ORBit_small_getepv(CORBA_Object obj,CORBA_unsigned_long class_id)1062 ORBit_small_getepv (CORBA_Object obj, CORBA_unsigned_long class_id)
1063 {
1064 	PortableServer_ServantBase *servant;
1065 	PortableServer_ClassInfo   *class_info;
1066 	CORBA_unsigned_long         offset;
1067 	ORBit_POAObject             pobj;
1068 
1069 	if (obj->adaptor_obj->interface->adaptor_type != ORBIT_ADAPTOR_POA)
1070 		return NULL;
1071 
1072 	pobj        = (ORBit_POAObject)obj->adaptor_obj;
1073 	servant     = pobj->servant;
1074 	class_info  = servant->vepv[0]->_private;
1075 	g_assert (class_info != NULL);
1076 	g_assert (class_id < class_info->vepvlen);
1077 	offset     = class_info->vepvmap [class_id];
1078 
1079 	return servant->vepv [offset];
1080 }
1081 #endif
1082 
1083 struct _ORBitAsyncQueueEntry {
1084 	GIOPMessageQueueEntry   mqe;
1085 	CORBA_Object            obj;
1086 	ORBitAsyncInvokeFunc    fn;
1087 	gpointer                user_data;
1088 	ORBit_IMethod          *m_data;
1089 	CORBA_completion_status completion_status;
1090 };
1091 
1092 void
ORBit_small_demarshal_async(ORBitAsyncQueueEntry * aqe,gpointer ret,gpointer * args,CORBA_Environment * ev)1093 ORBit_small_demarshal_async (ORBitAsyncQueueEntry *aqe,
1094 			     gpointer              ret,
1095 			     gpointer             *args,
1096 			     CORBA_Environment    *ev)
1097 {
1098 	g_return_if_fail (aqe->mqe.buffer != NULL);
1099 
1100 	switch (orbit_small_demarshal (aqe->obj, &aqe->mqe.cnx, aqe->mqe.buffer, ev,
1101 				       ret, aqe->m_data, args)) {
1102 	case MARSHAL_SYS_EXCEPTION_COMPLETE:
1103 		aqe->completion_status = CORBA_COMPLETED_YES;
1104 		dprintf (MESSAGES, "Sys exception completed on id 0x%x\n\n",
1105 			 aqe->mqe.request_id);
1106 		goto system_exception;
1107 
1108 	case MARSHAL_SYS_EXCEPTION_INCOMPLETE:
1109 		dprintf (MESSAGES, "Sys exception incomplete on id 0x%x\n\n",
1110 			 aqe->mqe.request_id);
1111 		goto system_exception;
1112 
1113 	case MARSHAL_EXCEPTION_COMPLETE:
1114 		dprintf (MESSAGES, "Clean demarshal of exception on id 0x%x\n\n",
1115 			 aqe->mqe.request_id);
1116 		break;
1117 
1118 	case MARSHAL_RETRY:
1119 		g_warning ("Retry demarshal failed on id 0x%x\n\n", aqe->mqe.request_id);
1120 		return;
1121 
1122 	case MARSHAL_CLEAN:
1123 		dprintf (MESSAGES, "Clean demarshal on id 0x%x\n\n",
1124 			 aqe->mqe.request_id);
1125 		break;
1126 	};
1127 	goto clean_out;
1128 
1129  system_exception:
1130 	tprintf ("[System exception comm failure] )");
1131 	CORBA_exception_set_system (ev, ex_CORBA_COMM_FAILURE,
1132 				    aqe->completion_status);
1133 
1134  clean_out:
1135 	tprintf_end_method ();
1136 }
1137 
1138 static void
async_recv_cb(ORBitAsyncQueueEntry * aqe)1139 async_recv_cb (ORBitAsyncQueueEntry *aqe)
1140 {
1141 	CORBA_Environment *ev, real_ev;
1142 
1143 	ev = &real_ev;
1144 	CORBA_exception_init (ev);
1145 
1146 	/* So we don't get invoked again */
1147 	aqe->mqe.async_cb = NULL;
1148 
1149 	if (!aqe->mqe.cnx ||
1150 	    aqe->mqe.cnx->parent.status == LINK_DISCONNECTED)
1151 		CORBA_exception_set_system (ev, ex_CORBA_COMM_FAILURE,
1152 					    aqe->completion_status);
1153 
1154 	if (aqe->mqe.cnx &&
1155 	    aqe->mqe.cnx->parent.status == LINK_TIMEOUT)
1156 		CORBA_exception_set_system (ev, ex_CORBA_TIMEOUT,
1157 					    aqe->completion_status);
1158 
1159 	if (aqe->fn)
1160 		aqe->fn (aqe->obj, aqe->m_data, aqe, aqe->user_data, ev);
1161 
1162 	ORBit_RootObject_release (aqe->obj);
1163 /*	ORBit_RootObject_release (aqe->m_data); */
1164 	giop_recv_list_destroy_queue_entry (&aqe->mqe);
1165 	g_free (aqe);
1166 	CORBA_exception_free (ev);
1167 }
1168 
1169 /**
1170  * ORBit_small_invoke_async:
1171  * @obj:
1172  * @m_data:
1173  * @fn:
1174  * @user_data:
1175  * @args:
1176  * @ctx:
1177  * @ev:
1178  *
1179  *     This method is used to invoke a remote (or local) method
1180  * asynchronously. @fn is called back on return - either with an empty
1181  * CORBA_Environment indicating success, or with the error.
1182  **/
1183 void
ORBit_small_invoke_async(CORBA_Object obj,ORBit_IMethod * m_data,ORBitAsyncInvokeFunc fn,gpointer user_data,gpointer * args,CORBA_Context ctx,CORBA_Environment * ev)1184 ORBit_small_invoke_async (CORBA_Object         obj,
1185 			  ORBit_IMethod       *m_data,
1186 			  ORBitAsyncInvokeFunc fn,
1187 			  gpointer             user_data,
1188 			  gpointer            *args,
1189 			  CORBA_Context        ctx,
1190 			  CORBA_Environment   *ev)
1191 {
1192 	CORBA_unsigned_long     request_id;
1193 	GIOPConnection         *cnx;
1194 	ORBitAsyncQueueEntry   *aqe = g_new (ORBitAsyncQueueEntry, 1);
1195 
1196 	if (obj->adaptor_obj) /* a local object, we need a remote handle */
1197 		aqe->obj = ORBit_objref_get_proxy (obj);
1198 	else
1199 		aqe->obj = ORBit_RootObject_duplicate (obj);
1200 
1201 	cnx = ORBit_object_get_connection (aqe->obj);
1202 
1203 	if (!cnx) {
1204 		tprintf ("Null connection on object '%p'\n", aqe->obj);
1205 		aqe->completion_status = CORBA_COMPLETED_NO;
1206 		goto system_exception;
1207 	}
1208 
1209 	request_id = GPOINTER_TO_UINT (aqe);
1210 	aqe->completion_status = CORBA_COMPLETED_NO;
1211 
1212 	giop_recv_list_setup_queue_entry (&aqe->mqe, cnx, GIOP_REPLY, request_id);
1213 
1214 	if (! (m_data->flags & ORBit_I_METHOD_1_WAY))
1215 		giop_recv_list_setup_queue_entry_async (
1216 			&aqe->mqe, (GIOPAsyncCallback) async_recv_cb);
1217 	else if (fn)
1218 		g_warning ("oneway method being invoked async with a callback");
1219 
1220 	if (!orbit_small_marshal (aqe->obj, cnx, &aqe->mqe, request_id,
1221 				  m_data, args, ctx))
1222 		goto system_exception;
1223 
1224 	if (m_data->flags & ORBit_I_METHOD_1_WAY)
1225 		giop_recv_list_destroy_queue_entry (&aqe->mqe);
1226 
1227 	aqe->completion_status = CORBA_COMPLETED_MAYBE;
1228 	aqe->fn = fn;
1229 	aqe->user_data = user_data;
1230 	/* FIXME: perenial ORBit_IMethod lifecycle issues */
1231 	aqe->m_data = /* ORBit_RootObject_duplicate */ (m_data);
1232 
1233  clean_out:
1234 	if (cnx)
1235 		giop_connection_unref (cnx);
1236 	tprintf_end_method ();
1237 	return;
1238 
1239  system_exception:
1240 	tprintf ("[System exception comm failure] )");
1241 	CORBA_exception_set_system (ev, ex_CORBA_COMM_FAILURE,
1242 				    aqe->completion_status);
1243 	g_free (aqe);
1244 	goto clean_out;
1245 }
1246 
1247 gpointer
ORBit_small_get_servant(CORBA_Object obj)1248 ORBit_small_get_servant (CORBA_Object obj)
1249 {
1250 	ORBit_POAObject pobj;
1251 
1252 	if (!obj || !obj->adaptor_obj || !obj->adaptor_obj->interface)
1253 		return NULL;
1254 
1255 	if (obj->adaptor_obj->interface->adaptor_type != ORBIT_ADAPTOR_POA) {
1256 		g_warning ("Not a poa object !");
1257 		return NULL;
1258 	}
1259 
1260 	pobj = (ORBit_POAObject)obj->adaptor_obj;
1261 
1262 	return pobj ? pobj->servant : NULL;
1263 }
1264 
1265 static ORBitConnectionStatus
get_status(GIOPConnection * cnx)1266 get_status (GIOPConnection *cnx)
1267 {
1268 	ORBitConnectionStatus ret;
1269 
1270 	g_return_val_if_fail (cnx != NULL, ORBIT_CONNECTION_DISCONNECTED);
1271 
1272 	switch (link_connection_get_status (LINK_CONNECTION (cnx))) {
1273 	case LINK_CONNECTED:
1274 		ret = ORBIT_CONNECTION_CONNECTED;
1275 		break;
1276 	case LINK_CONNECTING:
1277 		ret = ORBIT_CONNECTION_CONNECTED;
1278 		break;
1279 	default:
1280 		ret = ORBIT_CONNECTION_DISCONNECTED;
1281 		break;
1282 	}
1283 	return ret;
1284 }
1285 
1286 ORBitConnectionStatus
ORBit_small_get_connection_status(CORBA_Object obj)1287 ORBit_small_get_connection_status (CORBA_Object obj)
1288 {
1289 	ORBitConnectionStatus ret;
1290 
1291 	g_return_val_if_fail (obj != CORBA_OBJECT_NIL,
1292 			      ORBIT_CONNECTION_DISCONNECTED);
1293 
1294 	if (ORBit_small_get_servant (obj))
1295 		ret = ORBIT_CONNECTION_IN_PROC;
1296 	else {
1297 		GIOPConnection *cnx;
1298 
1299 		cnx = ORBit_object_get_connection (obj);
1300 
1301 		if (cnx) {
1302 			ret = get_status (cnx);
1303 			giop_connection_unref (cnx);
1304 		} else
1305 			ret = ORBIT_CONNECTION_DISCONNECTED;
1306 	}
1307 
1308 	return ret;
1309 }
1310 
1311 ORBitConnectionStatus
ORBit_small_listen_for_broken(CORBA_Object obj,GCallback fn,gpointer user_data)1312 ORBit_small_listen_for_broken (CORBA_Object obj,
1313 			       GCallback    fn,
1314 			       gpointer     user_data)
1315 {
1316 	ORBitConnectionStatus ret;
1317 
1318 	if (!obj)
1319 		ret = ORBIT_CONNECTION_DISCONNECTED;
1320 
1321 	else if (ORBit_small_get_servant (obj))
1322 		ret = ORBIT_CONNECTION_IN_PROC;
1323 
1324 	else {
1325 		GIOPConnection *cnx;
1326 
1327 		cnx = ORBit_object_get_connection (obj);
1328 
1329 		if (cnx) {
1330 			ret = get_status (cnx);
1331 			link_connection_add_broken_cb
1332 				(LINK_CONNECTION (cnx),
1333 				 (LinkBrokenCallback)fn, user_data);
1334 			giop_connection_unref (cnx);
1335 		} else
1336 			ret = ORBIT_CONNECTION_DISCONNECTED;
1337 	}
1338 
1339 	return ret;
1340 }
1341 
1342 ORBitConnectionStatus
ORBit_small_unlisten_for_broken_full(CORBA_Object obj,GCallback fn,gpointer user_data)1343 ORBit_small_unlisten_for_broken_full (CORBA_Object obj,
1344 				      GCallback    fn,
1345 				      gpointer     user_data)
1346 {
1347 	ORBitConnectionStatus ret;
1348 
1349 	if (!obj)
1350 		ret = ORBIT_CONNECTION_DISCONNECTED;
1351 
1352 	else if (ORBit_small_get_servant (obj))
1353 		ret = ORBIT_CONNECTION_IN_PROC;
1354 
1355 	else {
1356 		GIOPConnection *cnx;
1357 
1358 		cnx = ORBit_object_peek_connection (obj);
1359 
1360 		if (cnx) {
1361 			ret = get_status (cnx);
1362 			link_connection_remove_broken_cb
1363 				(LINK_CONNECTION (cnx),
1364 				 (LinkBrokenCallback)fn, user_data);
1365 			giop_connection_unref (cnx);
1366 		} else
1367 			ret = ORBIT_CONNECTION_DISCONNECTED;
1368 	}
1369 
1370 	return ret;
1371 }
1372 
1373 ORBitConnectionStatus
ORBit_small_unlisten_for_broken(CORBA_Object obj,GCallback fn)1374 ORBit_small_unlisten_for_broken (CORBA_Object obj,
1375 				 GCallback    fn)
1376 {
1377 	return ORBit_small_unlisten_for_broken_full (obj, fn, NULL);
1378 }
1379 
1380 ORBitConnection *
ORBit_small_get_connection_ref(CORBA_Object obj)1381 ORBit_small_get_connection_ref (CORBA_Object obj)
1382 {
1383 	return (ORBitConnection *) ORBit_object_get_connection (obj);
1384 }
1385 
1386 ORBitConnection *
ORBit_small_get_connection(CORBA_Object obj)1387 ORBit_small_get_connection (CORBA_Object obj)
1388 {
1389 	ORBitConnection *cnx;
1390 
1391 	cnx = ORBit_small_get_connection_ref (obj);
1392 
1393 	/* This sucks but compatibily */
1394 	ORBit_small_connection_unref (cnx);
1395 
1396 	return cnx;
1397 }
1398 
1399 void
ORBit_small_connection_unref(ORBitConnection * cnx)1400 ORBit_small_connection_unref (ORBitConnection *cnx)
1401 {
1402 	if (cnx)
1403 		giop_connection_unref (GIOP_CONNECTION (cnx));
1404 }
1405 
1406 void
ORBit_connection_set_max_buffer(ORBitConnection * cnx,gulong max_buffer_bytes)1407 ORBit_connection_set_max_buffer (ORBitConnection *cnx,
1408 				 gulong           max_buffer_bytes)
1409 {
1410 	LinkConnection *lcnx = (LinkConnection *) cnx;
1411 
1412 	g_return_if_fail (LINK_IS_CONNECTION (lcnx));
1413 
1414 	link_connection_set_max_buffer (lcnx, max_buffer_bytes);
1415 }
1416