/*
* 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 "iiop-link.h"
#include <flick/encode/cdr.h>
#include <ctype.h>
flick_client_table_entry *client_table = 0;
unsigned int client_table_entries = 0;
unsigned int max_client_table_entries = 0;
/* Create a client reference */
CORBA_Client CORBA_BOA_Client_create(CORBA_BOA ths,
/* unsigned client_id, */
void *client_data,
CORBA_Environment *ev)
{
CORBA_Client cli;
cli = t_calloc(FLICK_PSEUDO_CLIENT_STRUCT, 1);
if (!cli)
goto err;
cli->boa = ths;
/* cli->id = client_id; */
cli->data = client_data;
/* Clear the exception */
CORBA_BOA_set_exception(ths, ev, CORBA_NO_EXCEPTION, 0, 0);
return cli;
err:
flick_set_exception(ths, ev, ex_CORBA_NO_MEMORY,
0, CORBA_COMPLETED_NO);
fprintf(stderr,
"Error: can't malloc memory for new Client.\n");
return 0;
}
/*
* This is called from the client loop to (1) find the target object of a
* message, (2) extract the `GIOP::RequestHeader.request_id' field of the
* request, and (3) set the message stream pointer to point after the
* `GIOP::ReplyHeader'.
*/
static CORBA_Client find_client(CORBA_BOA ths,
FLICK_BUFFER *input_buffer,
/* OUT */ CORBA_Invocation_id *request_id,
/* OUT */ flick_client_work_func *func,
/* OUT */ FLICK_TARGET *obj,
CORBA_Environment *ev)
{
char *cursor;
char message_byte_order;
unsigned int service_context_seq_len;
unsigned int service_context_len;
unsigned int i;
/*****/
/* Pluck the byte order out of the GIOP MessageHeader structure. */
message_byte_order = ((char *) input_buffer->buf_start)[6];
if ((((char *) input_buffer->buf_start) + 4 + 2 + 1 + 1 + 4 + 4)
> ((char *) input_buffer->buf_end))
goto error;
/* Skip past the `GIOP::MessageHeader' structure. */
cursor = ((char *) input_buffer->buf_start)
+ 4 /* GIOP::MessageHeader.magic */
+ 2 /* GIOP::MessageHeader.GIOP_version */
+ 1 /* GIOP::MessageHeader.byte_order */
+ 1 /* GIOP::MessageHeader.message_type */
+ 4 /* GIOP::MessageHeader.message_size */
;
/* Parse the `GIOP::ReplyHeader.service_context' list. */
service_context_seq_len = *(unsigned int *) cursor;
if (flick_is_little_endian != message_byte_order)
service_context_seq_len = swap_long(service_context_seq_len);
cursor += 4;
for (i = 0; i < service_context_seq_len; ++i) {
/* Skip the `IOP::ServiceContext.context_id'. */
cursor += 4;
if( (void *)(cursor + 4) > input_buffer->buf_end )
goto error;
/* Skip the `IOP::ServiceContext.context_data' sequence. */
service_context_len = *(unsigned int *) cursor;
if (flick_is_little_endian != message_byte_order)
service_context_len = swap_long(service_context_len);
cursor += 4;
/*
* Note: It is always right to 4-byte align here, because the
* last service context will be followed by the unsigned int
* `GIOP::RequestHeader.request_id'.
*/
cursor += (service_context_len + 3) & ~3;
}
if( (void *)(cursor + 4 + 4 + 4) > input_buffer->buf_end )
goto error;
/* Save the `GIOP::ReplyHeader.request_id'. */
*request_id = *(CORBA_Invocation_id *) cursor;
if (flick_is_little_endian != message_byte_order)
*request_id = swap_long(*request_id);
cursor += 4;
if( (void *)cursor > input_buffer->buf_end )
goto error;
/*
* Now `cursor' is pointing to the `GIOP::ReplyHeader.reply_status',
* and we can initailize the message stream pointer for the server
* dispatch function.
*/
input_buffer->buf_current = cursor;
/*
* See if this client has an outstanding request for this reply.
*
* XXX --- We do a linear search through the list of request IDs.
* This is painfully inefficient, but hey, it's runtime, right? :-\
*/
for (i = 0; i < (unsigned) client_table_entries; i++) {
if (client_table[i].inv_id == *request_id) {
CORBA_Client cli;
*func = client_table[i].func;
*obj = client_table[i].obj;
cli = client_table[i].client;
/* remove this table entry */
client_table[i] = client_table[--client_table_entries];
return cli;
}
}
flick_set_exception(ths, ev, ex_CORBA_NO_IMPLEMENT,
0, CORBA_COMPLETED_NO);
return 0;
error:
flick_set_exception(ths, ev, ex_CORBA_COMM_FAILURE,
0, CORBA_COMPLETED_NO);
return 0;
}
/*
* Handle requests for the client.
*
* This function checks for incoming replies, and calls the dispatch
* function to handle any that need servicing.
*
* If multiple messages are waiting, they will be received and handled.
* This call will not block except to receive the remainder of an
* incomplete message.
*/
void CORBA_BOA_handle_replies(CORBA_BOA ths,
int num_handle,
CORBA_Environment *ev)
{
fd_set fds;
static int maxconn = -1;
static FLICK_BUFFER the_buf = {0, 0, 0, 0, 0, 0};
static FLICK_BUFFER return_buf = {0, 0, 0, 0, 0, 0};
static int *clients = 0;
static int client_cur = 0;
static int client_max = 0;
int handled = 0;
int sock = ths->socket_fd;
/* allocate the buffers, if not done already */
if (!the_buf.real_buf_start) {
the_buf.real_buf_start
= the_buf.buf_read
= the_buf.buf_start
= the_buf.buf_current
= t_calloc(char, 8192);
the_buf.real_buf_end
= the_buf.buf_end
= ((char *) the_buf.buf_start) + 8192;
return_buf.real_buf_start
= return_buf.real_buf_end
= return_buf.buf_read = 0;
return_buf.buf_start
= return_buf.buf_current
= t_calloc(char, 8192);
return_buf.buf_end = ((char *) return_buf.buf_start) + 8192;
if(!the_buf.buf_start || !return_buf.buf_start) {
flick_set_exception(ths, ev, ex_CORBA_NO_MEMORY,
0, CORBA_COMPLETED_NO);
perror("Insufficient memory for server buffers");
return;
}
}
/* Bind a port for this skeleton function */
if (!ths->connected) {
struct sockaddr_in server;
int len = sizeof(struct sockaddr_in);
if (bind(sock,
(struct sockaddr *)ths->ipaddr,
sizeof(*ths->ipaddr)) != 0) {
perror("cannot `bind' to socket");
flick_set_exception(ths, ev, ex_CORBA_COMM_FAILURE,
0, CORBA_COMPLETED_NO);
return;
}
if ((getsockname(sock, (struct sockaddr *)&server, &len) != 0)
|| (listen(sock, 8) != 0)) {
perror("cannot `getsockname' or `listen', "
"port may be in use");
flick_set_exception(ths, ev, ex_CORBA_COMM_FAILURE,
0, CORBA_COMPLETED_NO);
return;
}
ths->connected = 1;
}
if (sock > maxconn)
maxconn = sock;
/* Accept new connections and read client replies. */
do {
static struct timeval nowait = { 0, 0 };
CORBA_Client cli;
flick_client_work_func func;
flick_msg_struct_t msg;
FLICK_TARGET obj;
CORBA_Invocation_id request_id;
int i;
int qty;
/* set the file descriptor list (every time) */
FD_ZERO(&fds);
FD_SET(sock, &fds);
for (i = 0; i < client_cur; i++)
if (clients[i] >= 0)
FD_SET(clients[i], &fds);
qty = select(maxconn + 1, &fds, 0, 0,
(num_handle ? 0 : &nowait));
for (i = 0; i < client_cur && qty; i++) {
if ((clients[i] >= 0)
&& FD_ISSET(clients[i], &fds)) {
do {
request_id = 0;
if (!flick_server_get_request(
clients[i],
&the_buf)) {
/*
* Error receiving the mesg.
* Client FD is closed by
* `flick_server_get_request'.
*/
clients[i] = -1;
} else {
cli = find_client(ths,
&the_buf,
&request_id,
&func,
&obj,
ev);
if (ev->_major
!= CORBA_NO_EXCEPTION) {
/* Error finding
client. */
return;
}
msg.buf
= msg.hdr
= the_buf.buf_start;
msg.msg = the_buf.buf_current;
msg.msg_len
= (unsigned int)
((char *)
the_buf.buf_end
- (char *)
the_buf.buf_start);
func(cli, &msg, request_id,
obj);
handled++;
}
#if 0
if (!CORBA_Object_is_nil(obj, ev))
CORBA_Object_release(obj, ev);
#endif
} while (flick_buffer_contains_more(&the_buf));
qty--;
}
}
if (FD_ISSET(sock, &fds)) {
int pos = -1;
qty--;
for (i = 0; i < client_cur; i++)
if (clients[i] < 0)
break;
if (i < client_cur)
pos = i;
else {
pos = client_cur++;
if (client_cur > client_max) {
client_max += 10;
clients = t_realloc(clients, int,
client_max);
if (!clients) {
flick_set_exception(
ths, ev,
ex_CORBA_NO_MEMORY,
0, CORBA_COMPLETED_NO);
return;
}
}
}
clients[pos] = accept(sock, 0, 0);
if (clients[pos] > maxconn)
maxconn = clients[pos];
}
} while (handled < num_handle);
/* Successful completion (we serviced at least num_handle replies) */
CORBA_BOA_set_exception(ths, ev, CORBA_NO_EXCEPTION, 0, 0);
}
/* End of file. */
syntax highlighted by Code2HTML, v. 0.9.1