/** * 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; }
/* * 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; }