nchan.c (57429) | nchan.c (60573) |
---|---|
1/* 2 * Copyright (c) 1999 Markus Friedl. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 14 unchanged lines hidden (view full) --- 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30#include "includes.h" | 1/* 2 * Copyright (c) 1999 Markus Friedl. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 14 unchanged lines hidden (view full) --- 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30#include "includes.h" |
31RCSID("$Id: nchan.c,v 1.10 2000/01/10 10:15:28 markus Exp $"); | 31RCSID("$Id: nchan.c,v 1.17 2000/05/08 17:44:54 markus Exp $"); |
32 33#include "ssh.h" 34 35#include "buffer.h" 36#include "packet.h" 37#include "channels.h" 38#include "nchan.h" 39 | 32 33#include "ssh.h" 34 35#include "buffer.h" 36#include "packet.h" 37#include "channels.h" 38#include "nchan.h" 39 |
40static void chan_send_ieof(Channel *c); 41static void chan_send_oclose(Channel *c); 42static void chan_shutdown_write(Channel *c); 43static void chan_shutdown_read(Channel *c); 44static void chan_delete_if_full_closed(Channel *c); | 40#include "ssh2.h" 41#include "compat.h" |
45 | 42 |
43/* functions manipulating channel states */ |
|
46/* 47 * EVENTS update channel input/output states execute ACTIONS 48 */ | 44/* 45 * EVENTS update channel input/output states execute ACTIONS 46 */ |
49 | |
50/* events concerning the INPUT from socket for channel (istate) */ | 47/* events concerning the INPUT from socket for channel (istate) */ |
51void 52chan_rcvd_oclose(Channel *c) | 48chan_event_fn *chan_rcvd_oclose = NULL; 49chan_event_fn *chan_read_failed = NULL; 50chan_event_fn *chan_ibuf_empty = NULL; 51/* events concerning the OUTPUT from channel for socket (ostate) */ 52chan_event_fn *chan_rcvd_ieof = NULL; 53chan_event_fn *chan_write_failed = NULL; 54chan_event_fn *chan_obuf_empty = NULL; 55/* 56 * ACTIONS: should never update the channel states 57 */ 58static void chan_send_ieof1(Channel *c); 59static void chan_send_oclose1(Channel *c); 60static void chan_send_close2(Channel *c); 61static void chan_send_eof2(Channel *c); 62 63/* channel cleanup */ 64chan_event_fn *chan_delete_if_full_closed = NULL; 65 66/* helper */ 67static void chan_shutdown_write(Channel *c); 68static void chan_shutdown_read(Channel *c); 69 70/* 71 * SSH1 specific implementation of event functions 72 */ 73 74static void 75chan_rcvd_oclose1(Channel *c) |
53{ | 76{ |
77 debug("channel %d: rcvd oclose", c->self); |
|
54 switch (c->istate) { 55 case CHAN_INPUT_WAIT_OCLOSE: | 78 switch (c->istate) { 79 case CHAN_INPUT_WAIT_OCLOSE: |
56 debug("channel %d: INPUT_WAIT_OCLOSE -> INPUT_CLOSED [rcvd OCLOSE]", c->self); | 80 debug("channel %d: input wait_oclose -> closed", c->self); |
57 c->istate = CHAN_INPUT_CLOSED; 58 break; 59 case CHAN_INPUT_OPEN: | 81 c->istate = CHAN_INPUT_CLOSED; 82 break; 83 case CHAN_INPUT_OPEN: |
60 debug("channel %d: INPUT_OPEN -> INPUT_CLOSED [rvcd OCLOSE, send IEOF]", c->self); | 84 debug("channel %d: input open -> closed", c->self); |
61 chan_shutdown_read(c); | 85 chan_shutdown_read(c); |
62 chan_send_ieof(c); | 86 chan_send_ieof1(c); |
63 c->istate = CHAN_INPUT_CLOSED; 64 break; 65 case CHAN_INPUT_WAIT_DRAIN: 66 /* both local read_failed and remote write_failed */ | 87 c->istate = CHAN_INPUT_CLOSED; 88 break; 89 case CHAN_INPUT_WAIT_DRAIN: 90 /* both local read_failed and remote write_failed */ |
67 log("channel %d: INPUT_WAIT_DRAIN -> INPUT_CLOSED [rvcd OCLOSE, send IEOF]", c->self); 68 debug("channel %d: INPUT_WAIT_DRAIN -> INPUT_CLOSED [rvcd OCLOSE, send IEOF]", c->self); 69 chan_send_ieof(c); | 91 log("channel %d: input drain -> closed", c->self); 92 chan_send_ieof1(c); |
70 c->istate = CHAN_INPUT_CLOSED; 71 break; 72 default: | 93 c->istate = CHAN_INPUT_CLOSED; 94 break; 95 default: |
73 error("protocol error: chan_rcvd_oclose %d for istate %d", c->self, c->istate); | 96 error("channel %d: protocol error: chan_rcvd_oclose for istate %d", 97 c->self, c->istate); |
74 return; 75 } | 98 return; 99 } |
76 chan_delete_if_full_closed(c); | |
77} | 100} |
78void 79chan_read_failed(Channel *c) | 101static void 102chan_read_failed_12(Channel *c) |
80{ | 103{ |
104 debug("channel %d: read failed", c->self); |
|
81 switch (c->istate) { 82 case CHAN_INPUT_OPEN: | 105 switch (c->istate) { 106 case CHAN_INPUT_OPEN: |
83 debug("channel %d: INPUT_OPEN -> INPUT_WAIT_DRAIN [read failed]", c->self); | 107 debug("channel %d: input open -> drain", c->self); |
84 chan_shutdown_read(c); 85 c->istate = CHAN_INPUT_WAIT_DRAIN; | 108 chan_shutdown_read(c); 109 c->istate = CHAN_INPUT_WAIT_DRAIN; |
110 if (buffer_len(&c->input) == 0) { 111 debug("channel %d: input: no drain shortcut", c->self); 112 chan_ibuf_empty(c); 113 } |
|
86 break; 87 default: | 114 break; 115 default: |
88 error("internal error: we do not read, but chan_read_failed %d for istate %d", 89 c->self, c->istate); | 116 error("channel %d: internal error: we do not read, but chan_read_failed for istate %d", 117 c->self, c->istate); |
90 break; 91 } 92} | 118 break; 119 } 120} |
93void 94chan_ibuf_empty(Channel *c) | 121static void 122chan_ibuf_empty1(Channel *c) |
95{ | 123{ |
124 debug("channel %d: ibuf empty", c->self); |
|
96 if (buffer_len(&c->input)) { | 125 if (buffer_len(&c->input)) { |
97 error("internal error: chan_ibuf_empty %d for non empty buffer", c->self); | 126 error("channel %d: internal error: chan_ibuf_empty for non empty buffer", 127 c->self); |
98 return; 99 } 100 switch (c->istate) { 101 case CHAN_INPUT_WAIT_DRAIN: | 128 return; 129 } 130 switch (c->istate) { 131 case CHAN_INPUT_WAIT_DRAIN: |
102 debug("channel %d: INPUT_WAIT_DRAIN -> INPUT_WAIT_OCLOSE [inbuf empty, send IEOF]", c->self); 103 chan_send_ieof(c); | 132 debug("channel %d: input drain -> wait_oclose", c->self); 133 chan_send_ieof1(c); |
104 c->istate = CHAN_INPUT_WAIT_OCLOSE; 105 break; 106 default: | 134 c->istate = CHAN_INPUT_WAIT_OCLOSE; 135 break; 136 default: |
107 error("internal error: chan_ibuf_empty %d for istate %d", c->self, c->istate); | 137 error("channel %d: internal error: chan_ibuf_empty for istate %d", 138 c->self, c->istate); |
108 break; 109 } 110} | 139 break; 140 } 141} |
111 112/* events concerning the OUTPUT from channel for socket (ostate) */ 113void 114chan_rcvd_ieof(Channel *c) | 142static void 143chan_rcvd_ieof1(Channel *c) |
115{ | 144{ |
145 debug("channel %d: rcvd ieof", c->self); 146 if (c->type != SSH_CHANNEL_OPEN) { 147 debug("channel %d: non-open", c->self); 148 if (c->istate == CHAN_INPUT_OPEN) { 149 debug("channel %d: non-open: input open -> wait_oclose", c->self); 150 chan_shutdown_read(c); 151 chan_send_ieof1(c); 152 c->istate = CHAN_INPUT_WAIT_OCLOSE; 153 } else { 154 error("channel %d: istate %d != open", c->self, c->istate); 155 } 156 if (c->ostate == CHAN_OUTPUT_OPEN) { 157 debug("channel %d: non-open: output open -> closed", c->self); 158 chan_send_oclose1(c); 159 c->ostate = CHAN_OUTPUT_CLOSED; 160 } else { 161 error("channel %d: ostate %d != open", c->self, c->ostate); 162 } 163 return; 164 } |
|
116 switch (c->ostate) { 117 case CHAN_OUTPUT_OPEN: | 165 switch (c->ostate) { 166 case CHAN_OUTPUT_OPEN: |
118 debug("channel %d: OUTPUT_OPEN -> OUTPUT_WAIT_DRAIN [rvcd IEOF]", c->self); | 167 debug("channel %d: output open -> drain", c->self); |
119 c->ostate = CHAN_OUTPUT_WAIT_DRAIN; 120 break; 121 case CHAN_OUTPUT_WAIT_IEOF: | 168 c->ostate = CHAN_OUTPUT_WAIT_DRAIN; 169 break; 170 case CHAN_OUTPUT_WAIT_IEOF: |
122 debug("channel %d: OUTPUT_WAIT_IEOF -> OUTPUT_CLOSED [rvcd IEOF]", c->self); | 171 debug("channel %d: output wait_ieof -> closed", c->self); |
123 c->ostate = CHAN_OUTPUT_CLOSED; | 172 c->ostate = CHAN_OUTPUT_CLOSED; |
124 chan_delete_if_full_closed(c); | |
125 break; 126 default: | 173 break; 174 default: |
127 error("protocol error: chan_rcvd_ieof %d for ostate %d", c->self, c->ostate); | 175 error("channel %d: protocol error: chan_rcvd_ieof for ostate %d", 176 c->self, c->ostate); |
128 break; 129 } 130} | 177 break; 178 } 179} |
131void 132chan_write_failed(Channel *c) | 180static void 181chan_write_failed1(Channel *c) |
133{ | 182{ |
183 debug("channel %d: write failed", c->self); |
|
134 switch (c->ostate) { 135 case CHAN_OUTPUT_OPEN: | 184 switch (c->ostate) { 185 case CHAN_OUTPUT_OPEN: |
136 debug("channel %d: OUTPUT_OPEN -> OUTPUT_WAIT_IEOF [write failed]", c->self); 137 chan_send_oclose(c); | 186 debug("channel %d: output open -> wait_ieof", c->self); 187 chan_send_oclose1(c); |
138 c->ostate = CHAN_OUTPUT_WAIT_IEOF; 139 break; 140 case CHAN_OUTPUT_WAIT_DRAIN: | 188 c->ostate = CHAN_OUTPUT_WAIT_IEOF; 189 break; 190 case CHAN_OUTPUT_WAIT_DRAIN: |
141 debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [write failed]", c->self); 142 chan_send_oclose(c); | 191 debug("channel %d: output wait_drain -> closed", c->self); 192 chan_send_oclose1(c); |
143 c->ostate = CHAN_OUTPUT_CLOSED; | 193 c->ostate = CHAN_OUTPUT_CLOSED; |
144 chan_delete_if_full_closed(c); | |
145 break; 146 default: | 194 break; 195 default: |
147 error("internal error: chan_write_failed %d for ostate %d", c->self, c->ostate); | 196 error("channel %d: internal error: chan_write_failed for ostate %d", 197 c->self, c->ostate); |
148 break; 149 } 150} | 198 break; 199 } 200} |
151void 152chan_obuf_empty(Channel *c) | 201static void 202chan_obuf_empty1(Channel *c) |
153{ | 203{ |
204 debug("channel %d: obuf empty", c->self); |
|
154 if (buffer_len(&c->output)) { | 205 if (buffer_len(&c->output)) { |
155 debug("internal error: chan_obuf_empty %d for non empty buffer", c->self); | 206 error("channel %d: internal error: chan_obuf_empty for non empty buffer", 207 c->self); |
156 return; 157 } 158 switch (c->ostate) { 159 case CHAN_OUTPUT_WAIT_DRAIN: | 208 return; 209 } 210 switch (c->ostate) { 211 case CHAN_OUTPUT_WAIT_DRAIN: |
160 debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [obuf empty, send OCLOSE]", c->self); 161 chan_send_oclose(c); | 212 debug("channel %d: output drain -> closed", c->self); 213 chan_send_oclose1(c); |
162 c->ostate = CHAN_OUTPUT_CLOSED; | 214 c->ostate = CHAN_OUTPUT_CLOSED; |
163 chan_delete_if_full_closed(c); | |
164 break; 165 default: | 215 break; 216 default: |
166 error("internal error: chan_obuf_empty %d for ostate %d", c->self, c->ostate); | 217 error("channel %d: internal error: chan_obuf_empty for ostate %d", 218 c->self, c->ostate); |
167 break; 168 } 169} | 219 break; 220 } 221} |
170 171/* 172 * ACTIONS: should never update the channel states: c->istate or c->ostate 173 */ | |
174static void | 222static void |
175chan_send_ieof(Channel *c) | 223chan_send_ieof1(Channel *c) |
176{ | 224{ |
225 debug("channel %d: send ieof", c->self); |
|
177 switch (c->istate) { 178 case CHAN_INPUT_OPEN: 179 case CHAN_INPUT_WAIT_DRAIN: 180 packet_start(SSH_MSG_CHANNEL_INPUT_EOF); 181 packet_put_int(c->remote_id); 182 packet_send(); 183 break; 184 default: | 226 switch (c->istate) { 227 case CHAN_INPUT_OPEN: 228 case CHAN_INPUT_WAIT_DRAIN: 229 packet_start(SSH_MSG_CHANNEL_INPUT_EOF); 230 packet_put_int(c->remote_id); 231 packet_send(); 232 break; 233 default: |
185 error("internal error: channel %d: cannot send IEOF for istate %d", c->self, c->istate); | 234 error("channel %d: internal error: cannot send ieof for istate %d", 235 c->self, c->istate); |
186 break; 187 } 188} 189static void | 236 break; 237 } 238} 239static void |
190chan_send_oclose(Channel *c) | 240chan_send_oclose1(Channel *c) |
191{ | 241{ |
242 debug("channel %d: send oclose", c->self); |
|
192 switch (c->ostate) { 193 case CHAN_OUTPUT_OPEN: 194 case CHAN_OUTPUT_WAIT_DRAIN: 195 chan_shutdown_write(c); 196 buffer_consume(&c->output, buffer_len(&c->output)); 197 packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE); 198 packet_put_int(c->remote_id); 199 packet_send(); 200 break; 201 default: | 243 switch (c->ostate) { 244 case CHAN_OUTPUT_OPEN: 245 case CHAN_OUTPUT_WAIT_DRAIN: 246 chan_shutdown_write(c); 247 buffer_consume(&c->output, buffer_len(&c->output)); 248 packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE); 249 packet_put_int(c->remote_id); 250 packet_send(); 251 break; 252 default: |
202 error("internal error: channel %d: cannot send OCLOSE for ostate %d", c->self, c->istate); | 253 error("channel %d: internal error: cannot send oclose for ostate %d", 254 c->self, c->ostate); |
203 break; 204 } 205} | 255 break; 256 } 257} |
258static void 259chan_delete_if_full_closed1(Channel *c) 260{ 261 if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) { 262 debug("channel %d: full closed", c->self); 263 channel_free(c->self); 264 } 265} |
|
206 | 266 |
207/* helper */ | 267/* 268 * the same for SSH2 269 */ |
208static void | 270static void |
209chan_shutdown_write(Channel *c) | 271chan_rcvd_oclose2(Channel *c) |
210{ | 272{ |
211 /* shutdown failure is allowed if write failed already */ 212 debug("channel %d: shutdown_write", c->self); 213 if (shutdown(c->sock, SHUT_WR) < 0) 214 debug("chan_shutdown_write failed for #%d/fd%d: %.100s", 215 c->self, c->sock, strerror(errno)); | 273 debug("channel %d: rcvd close", c->self); 274 if (c->flags & CHAN_CLOSE_RCVD) 275 error("channel %d: protocol error: close rcvd twice", c->self); 276 c->flags |= CHAN_CLOSE_RCVD; 277 if (c->type == SSH_CHANNEL_LARVAL) { 278 /* tear down larval channels immediately */ 279 c->ostate = CHAN_OUTPUT_CLOSED; 280 c->istate = CHAN_INPUT_CLOSED; 281 return; 282 } 283 switch (c->ostate) { 284 case CHAN_OUTPUT_OPEN: 285 /* wait until a data from the channel is consumed if a CLOSE is received */ 286 debug("channel %d: output open -> drain", c->self); 287 c->ostate = CHAN_OUTPUT_WAIT_DRAIN; 288 break; 289 } 290 switch (c->istate) { 291 case CHAN_INPUT_OPEN: 292 debug("channel %d: input open -> closed", c->self); 293 chan_shutdown_read(c); 294 break; 295 case CHAN_INPUT_WAIT_DRAIN: 296 debug("channel %d: input drain -> closed", c->self); 297 chan_send_eof2(c); 298 break; 299 } 300 c->istate = CHAN_INPUT_CLOSED; |
216} 217static void | 301} 302static void |
218chan_shutdown_read(Channel *c) | 303chan_ibuf_empty2(Channel *c) |
219{ | 304{ |
220 debug("channel %d: shutdown_read", c->self); 221 if (shutdown(c->sock, SHUT_RD) < 0) 222 error("chan_shutdown_read failed for #%d/fd%d [i%d o%d]: %.100s", 223 c->self, c->sock, c->istate, c->ostate, strerror(errno)); | 305 debug("channel %d: ibuf empty", c->self); 306 if (buffer_len(&c->input)) { 307 error("channel %d: internal error: chan_ibuf_empty for non empty buffer", 308 c->self); 309 return; 310 } 311 switch (c->istate) { 312 case CHAN_INPUT_WAIT_DRAIN: 313 debug("channel %d: input drain -> closed", c->self); 314 if (!(c->flags & CHAN_CLOSE_SENT)) 315 chan_send_eof2(c); 316 c->istate = CHAN_INPUT_CLOSED; 317 break; 318 default: 319 error("channel %d: internal error: chan_ibuf_empty for istate %d", 320 c->self, c->istate); 321 break; 322 } |
224} 225static void | 323} 324static void |
226chan_delete_if_full_closed(Channel *c) | 325chan_rcvd_ieof2(Channel *c) |
227{ | 326{ |
327 debug("channel %d: rcvd eof", c->self); 328 if (c->ostate == CHAN_OUTPUT_OPEN) { 329 debug("channel %d: output open -> drain", c->self); 330 c->ostate = CHAN_OUTPUT_WAIT_DRAIN; 331 } 332} 333static void 334chan_write_failed2(Channel *c) 335{ 336 debug("channel %d: write failed", c->self); 337 switch (c->ostate) { 338 case CHAN_OUTPUT_OPEN: 339 debug("channel %d: output open -> closed", c->self); 340 chan_shutdown_write(c); /* ?? */ 341 c->ostate = CHAN_OUTPUT_CLOSED; 342 break; 343 case CHAN_OUTPUT_WAIT_DRAIN: 344 debug("channel %d: output drain -> closed", c->self); 345 chan_shutdown_write(c); 346 c->ostate = CHAN_OUTPUT_CLOSED; 347 break; 348 default: 349 error("channel %d: internal error: chan_write_failed for ostate %d", 350 c->self, c->ostate); 351 break; 352 } 353} 354static void 355chan_obuf_empty2(Channel *c) 356{ 357 debug("channel %d: obuf empty", c->self); 358 if (buffer_len(&c->output)) { 359 error("internal error: chan_obuf_empty %d for non empty buffer", 360 c->self); 361 return; 362 } 363 switch (c->ostate) { 364 case CHAN_OUTPUT_WAIT_DRAIN: 365 debug("channel %d: output drain -> closed", c->self); 366 chan_shutdown_write(c); 367 c->ostate = CHAN_OUTPUT_CLOSED; 368 break; 369 default: 370 error("channel %d: internal error: chan_obuf_empty for ostate %d", 371 c->self, c->ostate); 372 break; 373 } 374} 375static void 376chan_send_eof2(Channel *c) 377{ 378 debug("channel %d: send eof", c->self); 379 switch (c->istate) { 380 case CHAN_INPUT_WAIT_DRAIN: 381 packet_start(SSH2_MSG_CHANNEL_EOF); 382 packet_put_int(c->remote_id); 383 packet_send(); 384 break; 385 default: 386 error("channel %d: internal error: cannot send eof for istate %d", 387 c->self, c->istate); 388 break; 389 } 390} 391static void 392chan_send_close2(Channel *c) 393{ 394 debug("channel %d: send close", c->self); 395 if (c->ostate != CHAN_OUTPUT_CLOSED || 396 c->istate != CHAN_INPUT_CLOSED) { 397 error("channel %d: internal error: cannot send close for istate/ostate %d/%d", 398 c->self, c->istate, c->ostate); 399 } else if (c->flags & CHAN_CLOSE_SENT) { 400 error("channel %d: internal error: already sent close", c->self); 401 } else { 402 packet_start(SSH2_MSG_CHANNEL_CLOSE); 403 packet_put_int(c->remote_id); 404 packet_send(); 405 c->flags |= CHAN_CLOSE_SENT; 406 } 407} 408static void 409chan_delete_if_full_closed2(Channel *c) 410{ |
|
228 if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) { | 411 if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) { |
229 debug("channel %d: full closed", c->self); 230 channel_free(c->self); | 412 if (!(c->flags & CHAN_CLOSE_SENT)) { 413 chan_send_close2(c); 414 } 415 if ((c->flags & CHAN_CLOSE_SENT) && 416 (c->flags & CHAN_CLOSE_RCVD)) { 417 debug("channel %d: full closed2", c->self); 418 channel_free(c->self); 419 } |
231 } 232} | 420 } 421} |
422 423/* shared */ |
|
233void 234chan_init_iostates(Channel *c) 235{ 236 c->ostate = CHAN_OUTPUT_OPEN; 237 c->istate = CHAN_INPUT_OPEN; | 424void 425chan_init_iostates(Channel *c) 426{ 427 c->ostate = CHAN_OUTPUT_OPEN; 428 c->istate = CHAN_INPUT_OPEN; |
429 c->flags = 0; |
|
238} | 430} |
431 432/* init */ 433void 434chan_init(void) 435{ 436 if (compat20) { 437 chan_rcvd_oclose = chan_rcvd_oclose2; 438 chan_read_failed = chan_read_failed_12; 439 chan_ibuf_empty = chan_ibuf_empty2; 440 441 chan_rcvd_ieof = chan_rcvd_ieof2; 442 chan_write_failed = chan_write_failed2; 443 chan_obuf_empty = chan_obuf_empty2; 444 445 chan_delete_if_full_closed = chan_delete_if_full_closed2; 446 } else { 447 chan_rcvd_oclose = chan_rcvd_oclose1; 448 chan_read_failed = chan_read_failed_12; 449 chan_ibuf_empty = chan_ibuf_empty1; 450 451 chan_rcvd_ieof = chan_rcvd_ieof1; 452 chan_write_failed = chan_write_failed1; 453 chan_obuf_empty = chan_obuf_empty1; 454 455 chan_delete_if_full_closed = chan_delete_if_full_closed1; 456 } 457} 458 459/* helper */ 460static void 461chan_shutdown_write(Channel *c) 462{ 463 buffer_consume(&c->output, buffer_len(&c->output)); 464 if (compat20 && c->type == SSH_CHANNEL_LARVAL) 465 return; 466 /* shutdown failure is allowed if write failed already */ 467 debug("channel %d: close_write", c->self); 468 if (c->sock != -1) { 469 if (shutdown(c->sock, SHUT_WR) < 0) 470 debug("channel %d: chan_shutdown_write: shutdown() failed for fd%d: %.100s", 471 c->self, c->sock, strerror(errno)); 472 } else { 473 if (close(c->wfd) < 0) 474 log("channel %d: chan_shutdown_write: close() failed for fd%d: %.100s", 475 c->self, c->wfd, strerror(errno)); 476 c->wfd = -1; 477 } 478} 479static void 480chan_shutdown_read(Channel *c) 481{ 482 if (compat20 && c->type == SSH_CHANNEL_LARVAL) 483 return; 484 debug("channel %d: close_read", c->self); 485 if (c->sock != -1) { 486 if (shutdown(c->sock, SHUT_RD) < 0) 487 error("channel %d: chan_shutdown_read: shutdown() failed for fd%d [i%d o%d]: %.100s", 488 c->self, c->sock, c->istate, c->ostate, strerror(errno)); 489 } else { 490 if (close(c->rfd) < 0) 491 log("channel %d: chan_shutdown_read: close() failed for fd%d: %.100s", 492 c->self, c->rfd, strerror(errno)); 493 c->rfd = -1; 494 } 495} |
|