Esempio n. 1
0
/**
 * giop_send_buffer_write:
 * @buf: the buffer to write
 * @cnx: the connection to write it to.
 * 
 * Writes @buf to @cnx as a block.
 * 
 * Return value: 0 on sucess, non 0 on error.
 **/
int
giop_send_buffer_write (GIOPSendBuffer *buf,
			GIOPConnection *cnx,
			gboolean        blocking)
{
	int retval;
	LinkConnection *lcnx = LINK_CONNECTION (cnx);
	static LinkWriteOpts *non_block = NULL;

	if (!non_block)
		non_block = link_write_options_new (FALSE);

	/* FIXME: if a FRAGMENT, assert the 8 byte tail align,
	   &&|| giop_send_buffer_align (buf, 8); */

	if (g_thread_supported () 
	    && lcnx->timeout_msec 
	    && !lcnx->timeout_source_id
	    && !giop_send_buffer_is_oneway (buf)) {
		giop_timeout_add (cnx);
	}

	retval = link_connection_writev (lcnx, 
					 buf->iovecs,
					 buf->num_used, 
					 blocking ? NULL : non_block);

	if (!blocking && retval == LINK_IO_QUEUED_DATA)
		retval = 0;

	/* FIXME: we need to flag the connection disconnected on fatal error */

	return retval;
}
Esempio n. 2
0
/*
 * FIXME: we should definately handle things more asynchronously,
 * perhaps even at the expense of having to go to the GSource
 * twice in order to get fresh input (?)
 * or should we poll ourselves on the source to see what's up?
 *
 * The whole locking concept here looks broken to me,
 * especially since 'read' can flag the connection disconnected
 * giving a nice deadlock.
 */
gboolean
giop_connection_handle_input (LinkConnection *lcnx)
{
	GIOPRecvBuffer *buf;
	GIOPConnection *cnx = (GIOPConnection *) lcnx;

	do {
		int n;

		if (!cnx->incoming_msg)
			cnx->incoming_msg = giop_recv_buffer_use_buf (cnx);

		buf = cnx->incoming_msg;

		n = link_connection_read (
			lcnx, buf->cur, buf->left_to_read, FALSE);

		if (n == 0) /* We'll be back */
			return TRUE;

		if (n < 0 || !buf->left_to_read) /* HUP */
			goto msg_error;

/*		fprintf (stderr, "Read %d\n", n);
		giop_dump (stderr, buf->cur, n, 0); */

		buf->left_to_read -= n;
		buf->cur += n;

		if (buf->left_to_read == 0) {

#ifdef G_ENABLE_DEBUG
			if (giop_debug_hook_incoming_mangler)
				giop_debug_hook_incoming_mangler (buf);
#endif

			switch (buf->state) {

			case GIOP_MSG_READING_HEADER:
				if (giop_recv_msg_reading_body (buf, cnx->parent.is_auth)) {
					dprintf (ERRORS, "OOB incoming msg header data\n");
					goto msg_error;
				}
				buf->state = GIOP_MSG_READING_BODY;
				break;

			case GIOP_MSG_READING_BODY: {

				dprintf (GIOP, "Incoming IIOP body:\n");

				buf->cur = buf->message_body + 12;
				if ((buf->cur + buf->msg.header.message_size) > buf->end) {
					dprintf (ERRORS, "broken incoming length data\n");
					goto msg_error;
				}
				do_giop_dump (stderr, buf->cur, buf->msg.header.message_size, 12);

				buf->state = GIOP_MSG_READY;

				if (giop_recv_buffer_demarshal (buf)) {
					dprintf (ERRORS, "broken incoming header data\n");
					goto msg_error;
				}

				if (MORE_FRAGMENTS_FOLLOW (buf)) {
					if (giop_recv_buffer_handle_fragmented (&buf, cnx))
						goto msg_error;

					else {
						cnx->incoming_msg = NULL;
						goto frag_out;
					}

				} else if (buf->msg.header.message_type == GIOP_FRAGMENT) {
					if (giop_recv_buffer_handle_fragmented (&buf, cnx))
						goto msg_error;
					/* else last fragment */
				}
				break;
			}

			case GIOP_MSG_AWAITING_FRAGMENTS:
			case GIOP_MSG_READY:
				g_assert_not_reached ();
				break;
			}
		}

	} while (cnx->incoming_msg &&
		 buf->left_to_read > 0 &&
		 buf->state != GIOP_MSG_READY);

	cnx->incoming_msg = NULL;

	switch (buf->msg.header.message_type) {
	case GIOP_REPLY:
	case GIOP_LOCATEREPLY:
		dprintf (MESSAGES, "handling reply\n");
		if (handle_reply (buf)) /* dodgy inbound data, pull the cnx */
			link_connection_state_changed (lcnx, LINK_DISCONNECTED);
		break;

	case GIOP_REQUEST:
		dprintf (MESSAGES, "handling request\n");
		ORBit_handle_request (cnx->orb_data, buf);
		break;

	case GIOP_LOCATEREQUEST:
		dprintf (MESSAGES, "handling locate request\n");
		ORBit_handle_locate_request (cnx->orb_data, buf);
		break;

	case GIOP_CANCELREQUEST:
	case GIOP_MESSAGEERROR:
		dprintf (ERRORS, "dropping an unusual & unhandled input buffer 0x%x",
			 buf->msg.header.message_type);
		giop_recv_buffer_unuse (buf);
		break;

	case GIOP_CLOSECONNECTION:
		dprintf (MESSAGES, "received close connection\n");
		giop_recv_buffer_unuse (buf);
		link_connection_state_changed (lcnx, LINK_DISCONNECTED);
		break;

	case GIOP_FRAGMENT:
		dprintf (ERRORS, "Fragment got in the wrong channel\n");
	default:
		dprintf (ERRORS, "dropping an out of bound input buffer "
			 "on the floor 0x%x\n", buf->msg.header.message_type);
		goto msg_error;
		break;
	}

 frag_out:	
	return TRUE;

 msg_error:
	cnx->incoming_msg = NULL;

	buf->msg.header.message_type = GIOP_MESSAGEERROR;
	buf->msg.header.message_size = 0;

	giop_recv_buffer_unuse (buf);

	/* Zap it for badness.
	 * XXX We should probably handle oversized
	 * messages more graciously XXX */
	link_connection_state_changed (LINK_CONNECTION (cnx),
				       LINK_DISCONNECTED);

	return TRUE;
}