LWMsgStatus lwmsg_assoc_send( LWMsgAssoc* assoc, LWMsgTag type, void* object ) { LWMsgMessage message = LWMSG_MESSAGE_INITIALIZER; message.tag = type; message.data = object; return lwmsg_assoc_send_message(assoc, &message); }
static LWMsgStatus lwmsg_peer_task_dispatch_calls( PeerAssocTask* task ) { LWMsgStatus status = LWMSG_STATUS_PENDING; PeerCall* call = NULL; LWMsgCookie cookie = 0; LWMsgMessage message = LWMSG_MESSAGE_INITIALIZER; LWMsgRing* ring = NULL; LWMsgRing* next = NULL; LWMsgSessionString sessid = {0}; for (ring = task->active_outgoing_calls.next; ring != &task->active_outgoing_calls; ring = next) { next = ring->next; lwmsg_ring_remove(ring); call = LWMSG_OBJECT_FROM_MEMBER(ring, PeerCall, queue_ring); /* Undispatched outgoing call -- send request*/ if (!(call->state & PEER_CALL_DISPATCHED)) { call->state |= PEER_CALL_DISPATCHED; lwmsg_message_init(&task->outgoing_message); task->outgoing_message.tag = call->params.outgoing.in->tag; task->outgoing_message.data = call->params.outgoing.in->data; task->outgoing_message.cookie = call->cookie; task->outgoing_message.status = call->status; lwmsg_peer_log_message(task, &task->outgoing_message, LWMSG_TRUE); status = lwmsg_assoc_send_message(task->assoc, &task->outgoing_message); switch (status) { case LWMSG_STATUS_SUCCESS: break; case LWMSG_STATUS_PENDING: task->outgoing = LWMSG_TRUE; BAIL_ON_ERROR(status); break; case LWMSG_STATUS_MALFORMED: case LWMSG_STATUS_INVALID_HANDLE: /* The association should still be usable, so just fail the call */ lwmsg_message_init(&message); message.status = status; message.flags = LWMSG_MESSAGE_FLAG_REPLY | LWMSG_MESSAGE_FLAG_SYNTHETIC; message.cookie = call->cookie; lwmsg_peer_call_complete_outgoing(call, &message); status = LWMSG_STATUS_SUCCESS; break; default: BAIL_ON_ERROR(status); } } /* Cancelled outgoing call -- send cancel request */ else if ((call->state & PEER_CALL_DISPATCHED) && (call->state & PEER_CALL_CANCELLED) && call->status != LWMSG_STATUS_CANCELLED) { call->status = LWMSG_STATUS_CANCELLED; lwmsg_message_init(&task->outgoing_message); task->outgoing_message.flags = LWMSG_MESSAGE_FLAG_CONTROL; task->outgoing_message.status = LWMSG_STATUS_CANCELLED; task->outgoing_message.cookie = call->cookie; lwmsg_peer_log_message(task, &task->outgoing_message, LWMSG_TRUE); status = lwmsg_assoc_send_message(task->assoc, &task->outgoing_message); switch (status) { case LWMSG_STATUS_SUCCESS: break; case LWMSG_STATUS_PENDING: task->outgoing = LWMSG_TRUE; BAIL_ON_ERROR(status); break; default: BAIL_ON_ERROR(status); } } } for (ring = task->active_incoming_calls.next; ring != &task->active_incoming_calls; ring = next) { next = ring->next; lwmsg_ring_remove(ring); call = LWMSG_OBJECT_FROM_MEMBER(ring, PeerCall, queue_ring); /* Completed incoming call -- send reply */ if ((call->state & PEER_CALL_COMPLETED) && (call->state & PEER_CALL_DISPATCHED)) { /* Trace call completion */ if (call->task->session->peer->trace_end) { call->task->session->peer->trace_end( LWMSG_CALL(call), &call->params.incoming.out, call->status, call->task->session->peer->trace_data); } lwmsg_message_init(&task->outgoing_message); task->outgoing_message.flags = LWMSG_MESSAGE_FLAG_REPLY; task->outgoing_message.tag = call->params.incoming.out.tag; task->outgoing_message.data = call->params.incoming.out.data; task->outgoing_message.cookie = call->cookie; task->outgoing_message.status = call->status; cookie = call->cookie; /* It's now safe to destroy the incoming call parameters */ message.tag = call->params.incoming.in.tag; message.data = call->params.incoming.in.data; lwmsg_assoc_destroy_message(task->assoc, &message); /* Delete the call structure */ lwmsg_hash_remove_entry(&task->incoming_calls, call); lwmsg_peer_call_delete(call); do { status = lwmsg_assoc_send_message(task->assoc, &task->outgoing_message); switch (status) { case LWMSG_STATUS_SUCCESS: lwmsg_peer_log_message(task, &task->outgoing_message, LWMSG_FALSE); lwmsg_assoc_destroy_message(task->assoc, &task->outgoing_message); break; case LWMSG_STATUS_PENDING: task->outgoing = LWMSG_TRUE; task->destroy_outgoing = LWMSG_TRUE; BAIL_ON_ERROR(status); break; case LWMSG_STATUS_MALFORMED: case LWMSG_STATUS_INVALID_HANDLE: case LWMSG_STATUS_OVERFLOW: case LWMSG_STATUS_UNDERFLOW: /* Our reply could not be sent because the dispatch function gave us bogus response parameters. Send a synthetic reply instead so the caller at least knows the call is complete */ lwmsg_peer_session_string_for_session((LWMsgSession*) task->session, sessid); LWMSG_LOG_WARNING(task->session->peer->context, "(session:%s >> %u) Response payload could not be sent: %s", sessid, cookie, lwmsg_status_name(status)); lwmsg_assoc_destroy_message(task->assoc, &task->outgoing_message); lwmsg_message_init(&task->outgoing_message); task->outgoing_message.flags = LWMSG_MESSAGE_FLAG_REPLY | LWMSG_MESSAGE_FLAG_SYNTHETIC; task->outgoing_message.status = status; task->outgoing_message.cookie = cookie; status = LWMSG_STATUS_AGAIN; break; default: BAIL_ON_ERROR(status); } } while (status == LWMSG_STATUS_AGAIN); } } error: return status; }