static void nn_req_action_send (struct nn_req *self) { int rc; struct nn_msg msg; /* Send the request. */ nn_msg_cp (&msg, &self->request); rc = nn_xreq_send (&self->xreq.sockbase, &msg); /* If the request cannot be sent at the moment wait till new outbound pipe arrives. */ if (nn_slow (rc == -EAGAIN)) { nn_msg_term (&msg); self->state = NN_REQ_STATE_DELAYED; return; } /* Request was successfully sent. Set up the re-send timer in case the request gets lost somewhere further out in the topology. */ if (nn_fast (rc == 0)) { nn_timer_start (&self->timer, self->resend_ivl); self->state = NN_REQ_STATE_ACTIVE; return; } /* Unexpected error. */ errnum_assert (0, -rc); }
static int nn_req_send (struct nn_sockbase *self, struct nn_msg *msg) { int rc; struct nn_req *req; req = nn_cont (self, struct nn_req, xreq.sockbase); /* If there's a request in progress, cancel it. */ if (nn_slow (req->state != NN_REQ_STATE_IDLE)) { if (req->state == NN_REQ_STATE_UNSENT || req->state == NN_REQ_STATE_SENT) nn_msg_term (&req->request); if (req->state == NN_REQ_STATE_RECEIVED) nn_msg_term (&req->reply); nn_timer_term (&req->resend_timer); req->state = NN_REQ_STATE_IDLE; } /* Generate new request ID for the new request and put it into message header. The most important bit is set to 1 to indicate that this is the bottom of the backtrace stack. */ ++req->reqid; nn_assert (nn_chunkref_size (&msg->hdr) == 0); nn_chunkref_term (&msg->hdr); nn_chunkref_init (&msg->hdr, 4); nn_putl (nn_chunkref_data (&msg->hdr), req->reqid | 0x80000000); /* Store the message so that it can be re-sent if there's no reply. Then make a copy of it and send it. */ nn_msg_cp (&req->request, msg); rc = nn_xreq_send (&req->xreq.sockbase, msg); errnum_assert (rc == 0 || rc == -EAGAIN, -rc); /* If the request cannot be sent at the moment switch to UNSENT state. It will be sent as soon as a new outbound pipe arrives. */ if (nn_slow (rc == -EAGAIN)) { nn_msg_term (msg); req->state = NN_REQ_STATE_UNSENT; return 0; } /* If the request was successgfully sent set up the re-send timer in case it get lost somewhere further out in the topology. */ nn_timer_start (&req->resend_timer, req->resend_ivl); req->state = NN_REQ_STATE_SENT; return 0; }
static void nn_req_out (struct nn_sockbase *self, struct nn_pipe *pipe) { int rc; struct nn_req *req; struct nn_msg msg; req = nn_cont (self, struct nn_req, xreq.sockbase); /* Add the pipe to the underlying raw socket. */ nn_xreq_out (&req->xreq.sockbase, pipe); /* If the current request was not sent yet, send it now. */ if (req->state == NN_REQ_STATE_UNSENT) { nn_msg_cp (&msg, &req->request); rc = nn_xreq_send (&req->xreq.sockbase, &msg); errnum_assert (rc == 0, -rc); req->state = NN_REQ_STATE_SENT; } }
static void nn_req_timeout (const struct nn_cp_sink **self, struct nn_timer *timer) { int rc; struct nn_req *req; struct nn_msg msg; req = nn_cont (self, struct nn_req, sink); nn_assert (req->state == NN_REQ_STATE_SENT); /* Re-send the request. If it cannot be sent, just drop it. */ nn_msg_cp (&msg, &req->request); rc = nn_xreq_send (&req->xreq.sockbase, &msg); errnum_assert (rc == 0 || rc == -EAGAIN, -rc); if (nn_slow (rc == -EAGAIN)) nn_msg_term (&msg); /* Set up the next re-send timer. */ nn_timer_start (&req->resend_timer, req->resend_ivl); }