if (!(si->flags & SI_FL_INDEP_STR))
if (tick_isset(ic->rex))
ic->rex = tick_add_ifset(now_ms, ic->rto);
+ }
- if (likely((oc->flags & (CF_SHUTW|CF_WRITE_PARTIAL|CF_DONT_READ)) == CF_WRITE_PARTIAL &&
- (si_opposite(si)->flags & SI_FL_WAIT_ROOM))) {
- si_opposite(si)->flags &= ~SI_FL_WAIT_ROOM;
- si_chk_rcv(si_opposite(si));
- }
+ if ((si_opposite(si)->flags & SI_FL_WAIT_ROOM) &&
+ ((oc->flags & (CF_SHUTW|CF_WRITE_PARTIAL|CF_DONT_READ)) == CF_WRITE_PARTIAL ||
+ channel_is_empty(oc))) {
+ si_opposite(si)->flags &= ~SI_FL_WAIT_ROOM;
+ si_chk_rcv(si_opposite(si));
}
/* Notify the other side when we've injected data into the IC that
struct channel *oc = si_oc(si);
if (!(ic->flags & CF_SHUTR)) {
- if (!(ic->flags & CF_DONT_READ))
- si_want_put(si);
-
/* Read not closed, update FD status and timeout for reads */
if ((ic->flags & CF_DONT_READ) || co_data(ic)) {
- /* stop reading */
- si_stop_put(si);
+ /* stop reading, imposed by channel's policy or contents */
+ si_cant_put(si);
ic->rex = TICK_ETERNITY;
}
else {
}
/* it's time to try to receive */
- if (!(req->flags & (CF_SHUTR|CF_DONT_READ)))
- si_want_put(si_f);
-
si_chk_rcv(si_f);
-
- if (!(res->flags & (CF_SHUTR|CF_DONT_READ)))
- si_want_put(si_b);
-
si_chk_rcv(si_b);
/* let's recompute both sides states */
if (si->wait_event.wait_reason & SUB_CAN_RECV)
return 0;
- /* by default nothing to deliver */
- si_stop_put(si);
-
/* maybe we were called immediately after an asynchronous shutr */
if (ic->flags & CF_SHUTR)
return 1;
if (cs->flags & CS_FL_EOS)
goto out_shutdown_r;
+ /* start by claiming we'll want to receive and change our mind later if needed */
+ si_want_put(si);
+
if ((ic->flags & (CF_STREAMER | CF_STREAMER_FAST)) && !co_data(ic) &&
global.tune.idle_timer &&
(unsigned short)(now_ms - ic->last_read) >= global.tune.idle_timer) {
if (cs->flags & CS_FL_RCV_MORE)
si_cant_put(si);
- if (ret <= 0)
+ if (ret <= 0) {
+ si_stop_put(si);
break;
+ }
cur_read += ret;
ic->flags |= CF_READ_PARTIAL;
ic->total += ret;
- if ((ic->flags & CF_READ_DONTWAIT) || --read_poll <= 0)
+ if ((ic->flags & CF_READ_DONTWAIT) || --read_poll <= 0) {
+ /* we're stopped by the channel's policy */
+ si_cant_put(si);
break;
+ }
/* if too many bytes were missing from last read, it means that
* it's pointless trying to read again because the system does
* have exhausted system buffers. It's not worth trying
* again.
*/
- if (ic->flags & CF_STREAMER)
+ if (ic->flags & CF_STREAMER) {
+ /* we're stopped by the channel's policy */
+ si_cant_put(si);
break;
+ }
/* if we read a large block smaller than what we requested,
* it's almost certain we'll never get anything more.
*/
- if (ret >= global.tune.recv_enough)
+ if (ret >= global.tune.recv_enough) {
+ /* we're stopped by the channel's policy */
+ si_cant_put(si);
break;
+ }
}
/* if we are waiting for more space, don't try to read more data