struct msg * rsp_recv_next(struct context *ctx, struct conn *conn, bool alloc) { struct msg *msg; ASSERT((conn->type == CONN_DNODE_PEER_SERVER) || (conn->type == CONN_SERVER)); if (conn->eof) { msg = conn->rmsg; if (conn->dyn_mode) { if (conn->non_bytes_recv > MAX_CONN_ALLOWABLE_NON_RECV) { conn->err = EPIPE; return NULL; } conn->eof = 0; return msg; } /* server sent eof before sending the entire request */ if (msg != NULL) { conn->rmsg = NULL; ASSERT(msg->peer == NULL); ASSERT(!msg->request); log_error("eof s %d discarding incomplete rsp %"PRIu64" len " "%"PRIu32"", conn->sd, msg->id, msg->mlen); rsp_put(msg); } /* * We treat TCP half-close from a server different from how we treat * those from a client. On a FIN from a server, we close the connection * immediately by sending the second FIN even if there were outstanding * or pending requests. This is actually a tricky part in the FA, as * we don't expect this to happen unless the server is misbehaving or * it crashes */ conn->done = 1; log_debug(LOG_DEBUG, "s %d active %d is done", conn->sd, conn_active(conn)); return NULL; } msg = conn->rmsg; if (msg != NULL) { ASSERT(!msg->request); return msg; } if (!alloc) { return NULL; } msg = rsp_get(conn); if (msg != NULL) { conn->rmsg = msg; } return msg; }
struct msg * req_recv_next(struct context *ctx, struct conn *conn, bool alloc) { struct msg *msg; ASSERT((conn->type == CONN_DNODE_PEER_CLIENT) || (conn->type = CONN_CLIENT)); if (conn->eof) { msg = conn->rmsg; //if (conn->dyn_mode) { // if (conn->non_bytes_recv > MAX_CONN_ALLOWABLE_NON_RECV) { // conn->err = EPIPE; // return NULL; // } // conn->eof = 0; // return msg; //} /* client sent eof before sending the entire request */ if (msg != NULL) { conn->rmsg = NULL; ASSERT(msg->peer == NULL); ASSERT(msg->request && !msg->done); log_error("eof c %d discarding incomplete req %"PRIu64" len " "%"PRIu32"", conn->sd, msg->id, msg->mlen); req_put(msg); } /* * TCP half-close enables the client to terminate its half of the * connection (i.e. the client no longer sends data), but it still * is able to receive data from the proxy. The proxy closes its * half (by sending the second FIN) when the client has no * outstanding requests */ if (!conn_active(conn)) { conn->done = 1; log_debug(LOG_INFO, "c %d is done", conn->sd); } return NULL; } msg = conn->rmsg; if (msg != NULL) { ASSERT(msg->request); return msg; } if (!alloc) { return NULL; } msg = req_get(conn); if (msg != NULL) { conn->rmsg = msg; } return msg; }