/*
* Copyright (c) 1998, 1999 The University of Utah and
* the Computer Systems Laboratory at the University of Utah (CSL).
* All rights reserved.
*
* Permission to use, copy, modify and distribute this software is hereby
* granted provided that (1) source code retains these copyright, permission,
* and disclaimer notices, and (2) redistributions including binaries
* reproduce the notices in supporting documentation.
*
* THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
* IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
* ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* CSL requests users of this software to return to csl-dist@cs.utah.edu any
* improvements that they make and grant CSL redistribution rights.
*/
#include "mach3mig-link.h"
#include "flick/encode/mach3mig.h"
CORBA_ReferenceData *CORBA_BOA_get_id(CORBA_BOA ths, CORBA_Object obj,
CORBA_Environment *ev)
{
CORBA_ReferenceData *res;
int i;
char *name = 0;
for (i = 0; i < ths->obj_count; i++) {
if (ths->objs[i] == obj) {
name = ths->names[i];
break;
}
}
res = t_malloc(CORBA_ReferenceData, 1);
if (!res) {
flick_set_exception(ths, ev, ex_CORBA_NO_MEMORY,
0, CORBA_COMPLETED_NO);
return 0;
}
if (name) {
res->_length = strlen(name);
res->_maximum = res->_length;
res->_buffer = t_malloc(CORBA_octet, res->_maximum);
if (!res->_buffer) {
free(res);
flick_set_exception(ths, ev, ex_CORBA_NO_MEMORY,
0, CORBA_COMPLETED_NO);
return 0;
}
memcpy(res->_buffer, name, res->_length);
} else {
res->_length = res->_maximum = 0;
res->_buffer = 0;
}
CORBA_BOA_set_exception(ths, ev, CORBA_NO_EXCEPTION, 0, 0);
return res;
}
/* used to be called CORBA_BOA_obj_is_ready, which was entirely wrong.
see Section 8.2 of the CORBA 2.0 Spec.
This function will create an object of the given type and implementation. */
CORBA_Object CORBA_BOA_create(CORBA_BOA ths, CORBA_ReferenceData *obj_key,
const char *type_id, FLICK_SERVER impl,
CORBA_Environment *ev)
{
CORBA_Object *new_objs;
char **new_names;
char **new_types;
FLICK_SERVER *new_impls;
char *ref_key_buffer;
char *ref_type_id;
int type_id_len;
mach_port_t new_right;
/* Allocate the memory we need for the new object reference. */
type_id_len = strlen(type_id);
ref_key_buffer = t_malloc(char, obj_key->_length + 1);
ref_type_id = t_malloc(char, (type_id_len + 1));
if (!ref_key_buffer || !ref_type_id) {
if (ref_key_buffer) free(ref_key_buffer);
if (ref_type_id) free(ref_type_id);
flick_set_exception(ths, ev, ex_CORBA_NO_MEMORY,
0, CORBA_COMPLETED_NO);
fprintf(stderr,
"Error: can't malloc memory for new object.\n");
return 0;
}
/* Reallocate our BOA's vector of references. */
new_objs = t_realloc(ths->objs,
CORBA_Object,
(ths->obj_count + 1));
new_names = t_realloc(ths->names,
char *,
(ths->obj_count + 1));
new_types = t_realloc(ths->types,
char *,
(ths->obj_count + 1));
new_impls = t_realloc(ths->impls,
FLICK_SERVER,
(ths->obj_count + 1));
if (!new_objs || !new_names || !new_types || !new_impls) {
free(ref_key_buffer);
free(ref_type_id);
if (new_objs) free(new_objs);
if (new_names) free(new_names);
if (new_types) free(new_types);
if (new_impls) free(new_impls);
flick_set_exception(ths, ev, ex_CORBA_NO_MEMORY,
0, CORBA_COMPLETED_NO);
fprintf(stderr,
"Error: can't realloc memory for CORBA_BOA object "
"references.\n");
return 0;
}
/* allocate a port */
if (mach_port_allocate(mach_task_self(),
MACH_PORT_RIGHT_RECEIVE,
&new_right)
!= KERN_SUCCESS) {
free(ref_key_buffer);
free(ref_type_id);
free(new_objs);
free(new_names);
free(new_types);
flick_set_exception(ths, ev, ex_CORBA_INTERNAL,
0, CORBA_COMPLETED_NO);
fprintf(stderr,
"Error: can't allocate a receive port for object "
"reference.\n");
return 0;
}
memcpy(ref_key_buffer, obj_key->_buffer, obj_key->_length);
ref_key_buffer[obj_key->_length] = 0; /* null-terminate */
strncpy(ref_type_id, type_id, (type_id_len + 1));
/* check this port into the nameserver */
if (netname_check_in(ths->name_server_port,
ref_key_buffer,
mach_task_self(),
new_right)
!= KERN_SUCCESS) {
free(ref_key_buffer);
free(ref_type_id);
free(new_objs);
free(new_names);
free(new_types);
flick_set_exception(ths, ev, ex_CORBA_INTERNAL,
0, CORBA_COMPLETED_NO);
fprintf(stderr,
"Error: can't check in object to nameserver.\n");
return 0;
}
ths->objs = new_objs;
ths->names = new_names;
ths->types = new_types;
ths->impls = new_impls;
ths->impls[ths->obj_count] = impl;
ths->types[ths->obj_count] = ref_type_id;
ths->names[ths->obj_count] = ref_key_buffer;
ths->objs[ths->obj_count] = new_right;
ths->obj_count++;
/* Finally, print the URL--style stringified object ref. */
{
char *url;
url = CORBA_ORB_object_to_string(ths->orb, new_right, ev);
if (ev->_major != CORBA_NO_EXCEPTION)
return 0;
printf("Object `%s' is ready.\n", ref_key_buffer);
printf(" URL:\t%s\n", url);
free(url);
}
CORBA_BOA_set_exception(ths, ev, CORBA_NO_EXCEPTION, 0, 0);
return new_right;
}
void CORBA_BOA_impl_is_ready(CORBA_BOA ths, CORBA_Environment *ev)
{
mach_port_t task_self = mach_task_self();
mach_port_t portset;
int i;
kern_return_t res;
char *buffer;
mach_msg_header_t *request;
mig_reply_header_t *reply;
/*
* XXX - Here we specify the largest size message the server
* can receive. If necessary, change the value of
* MAX_REPLY_BUFFER_SIZE in runtime/headers/flick/link/mach3mig.h.
*/
int bufsize = MAX_REPLY_BUFFER_SIZE;
/* Allocate the send/receive buffer */
buffer = t_malloc(char, bufsize);
if (!buffer) {
flick_set_exception(ths, ev, ex_CORBA_NO_MEMORY,
0, CORBA_COMPLETED_NO);
return;
}
request = (mach_msg_header_t *) buffer;
reply = (mig_reply_header_t *) buffer;
/*
* Under normal conditions, we will never return. If we ever
* do, it is because of an unrecoverable error. Set the
* exception now, so handling the error is easy.
*/
flick_set_exception(ths, ev, ex_CORBA_INTERNAL,
0, CORBA_COMPLETED_NO);
/* Create a port set for all the objects' ports. */
if (mach_port_allocate(task_self,
MACH_PORT_RIGHT_PORT_SET,
&portset)
!= KERN_SUCCESS)
return;
/* Advertise our server name so clients can connect. */
for (i = 0; i < ths->obj_count; i++) {
/* place the object's port into our port set */
if (mach_port_move_member(task_self,
ths->objs[i],
portset)
!= KERN_SUCCESS)
return;
}
while (1) {
res = mach_msg(request, MACH_RCV_MSG, 0, bufsize,
portset, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
if (res != MACH_MSG_SUCCESS) {
fprintf(stderr, "Unsuccessful msg receive: %s",
mach_error_string(res));
goto bail;
}
while (res == MACH_MSG_SUCCESS) {
boolean_t ok;
/* XXX - linear search through objects to find the
correct server function to call. */
for (i = 0; i < ths->obj_count; i++) {
if (ths->objs[i] == request->msgh_local_port) {
ok = ths->impls[i](
request,
(mach_msg_header_t *) reply);
break;
}
}
/* check to make sure we found the object */
if (i == ths->obj_count || !ok) {
/* build an appropriate error */
struct flick_stub_state _stub_state = { 0, 0 };
mach_msg_header_t *OutHeadP
= (mach_msg_header_t *) reply;
mach_msg_header_t *InHeadP = request;
void *_buf_current, *_buf_end;
mig_reply_header_t *_buf_start;
unsigned int exstrlen
= sizeof(ex_CORBA_NO_IMPLEMENT);
unsigned int len = * (unsigned int *)
&InHeadP[1];
unsigned int msgsize = 24 + (exstrlen + 3) % 4;
unsigned int i;
flick_mach3mig_server_start_encode();
flick_mach3mig_encode_new_glob(msgsize
+ (len + 2) * 8,
_onerror1);
/*
* Copy the operation ID from the request.
* We have to prepend '$' for the reply name.
*/
flick_mach3mig_encode_new_chunk((len + 2) * 8);
flick_mach3mig_encode_unsigned32(
0, len + 1, unsigned int);
flick_mach3mig_encode_char8(
8, '$', char);
for (i = 0; i < len; i++)
flick_mach3mig_encode_char8(
i * 8 + 16,
*((char *)&InHeadP[1] + 12),
char);
flick_mach3mig_encode_end_chunk((len + 2) * 8);
flick_mach3mig_encode_new_chunk(msgsize);
flick_mach3mig_encode_unsigned32(
0,
CORBA_SYSTEM_EXCEPTION,
unsigned int);
flick_mach3mig_array_encode_string_c_type(
8, exstrlen, 1, 0, _type);
flick_mach3mig_array_encode_bcopy(
12,
ex_CORBA_NO_IMPLEMENT,
exstrlen);
flick_mach3mig_encode_unsigned32(
msgsize - 16, 0 /* minor code */,
unsigned int);
flick_mach3mig_encode_unsigned32(
msgsize - 8, CORBA_COMPLETED_NO,
unsigned int);
flick_mach3mig_encode_end_chunk(msgsize);
flick_mach3mig_encode_end_glob(msgsize +
(len + 2) * 8);
_onerror1:
flick_mach3mig_server_end_encode();
}
if (reply->Head.msgh_remote_port == MACH_PORT_NULL) {
/* no reply port, just get another request */
break;
}
if (ok && reply->RetCode == MIG_NO_REPLY) {
/* deallocate reply port right */
(void) mach_port_deallocate(
task_self,
reply->Head.msgh_remote_port);
break;
}
/* Send reply to prev request and receive another: */
res = mach_msg(&reply->Head,
MACH_SEND_MSG | MACH_RCV_MSG,
reply->Head.msgh_size,
bufsize,
portset,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL);
if (res != MACH_MSG_SUCCESS) {
if (res == MACH_SEND_INVALID_DEST) {
/* deallocate reply port right */
(void) mach_port_deallocate(
task_self,
reply->Head.msgh_remote_port);
} else {
fprintf(stderr,
"Unsuccessful msg "
"send/receive: %s",
mach_error_string(res));
goto bail;
}
}
/*
* XXX - check for reallocated buffer?
* The dispatch funcions should never realloc
* the buffer, so we shouldn't have to check.
*/
}
}
bail:
/* Should never be reached. */
/* but just in case, clean up everything... */
mach_port_destroy(task_self,
portset);
}
/* End of file. */
syntax highlighted by Code2HTML, v. 0.9.1