Mercurial > dropbear
comparison common-channel.c @ 397:2908122e9eed channel-fix
disapproval of revision '1250b8af44b62d8f4fe0f8d9fc7e7a1cc34e7e1c'
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sat, 03 Feb 2007 08:10:09 +0000 |
parents | e7c1a77d2921 |
children | a5bca950120d |
comparison
equal
deleted
inserted
replaced
396:e7c1a77d2921 | 397:2908122e9eed |
---|---|
179 /* Iterate through the channels, performing IO if available */ | 179 /* Iterate through the channels, performing IO if available */ |
180 void channelio(fd_set *readfds, fd_set *writefds) { | 180 void channelio(fd_set *readfds, fd_set *writefds) { |
181 | 181 |
182 struct Channel *channel; | 182 struct Channel *channel; |
183 unsigned int i; | 183 unsigned int i; |
184 int ret; | |
184 | 185 |
185 /* iterate through all the possible channels */ | 186 /* iterate through all the possible channels */ |
186 for (i = 0; i < ses.chansize; i++) { | 187 for (i = 0; i < ses.chansize; i++) { |
187 | 188 |
188 channel = ses.channels[i]; | 189 channel = ses.channels[i]; |
202 send_msg_channel_data(channel, 1, SSH_EXTENDED_DATA_STDERR); | 203 send_msg_channel_data(channel, 1, SSH_EXTENDED_DATA_STDERR); |
203 } | 204 } |
204 | 205 |
205 /* if we can read from the writefd, it might be closed, so we try to | 206 /* if we can read from the writefd, it might be closed, so we try to |
206 * see if it has errors */ | 207 * see if it has errors */ |
207 if (channel->writefd >= 0 && channel->writefd != channel->readfd | 208 if (IS_DROPBEAR_SERVER && channel->writefd >= 0 |
209 && channel->writefd != channel->readfd | |
208 && FD_ISSET(channel->writefd, readfds)) { | 210 && FD_ISSET(channel->writefd, readfds)) { |
209 if (channel->initconn) { | 211 if (channel->initconn) { |
210 /* Handling for "in progress" connection - this is needed | 212 /* Handling for "in progress" connection - this is needed |
211 * to avoid spinning 100% CPU when we connect to a server | 213 * to avoid spinning 100% CPU when we connect to a server |
212 * which doesn't send anything (tcpfwding) */ | 214 * which doesn't send anything (tcpfwding) */ |
257 TRACE(("writebuf size %d extrabuf ptr 0x%x extrabuf size %d", | 259 TRACE(("writebuf size %d extrabuf ptr 0x%x extrabuf size %d", |
258 cbuf_getused(channel->writebuf), | 260 cbuf_getused(channel->writebuf), |
259 channel->writebuf, | 261 channel->writebuf, |
260 channel->writebuf ? 0 : cbuf_getused(channel->extrabuf))) | 262 channel->writebuf ? 0 : cbuf_getused(channel->extrabuf))) |
261 | 263 |
262 if (!channel->sentclosed) { | 264 /* server chansession channels are special, since readfd mightn't |
263 | 265 * close in the case of "sleep 4 & echo blah" until the sleep is up */ |
264 /* check for exited - currently only used for server sessions, | 266 if (channel->type->checkclose) { |
265 * if the shell has exited etc */ | 267 if (channel->type->checkclose(channel)) { |
266 if (channel->type->checkclose) { | 268 closewritefd(channel); |
267 if (channel->type->checkclose(channel)) { | 269 closereadfd(channel, channel->readfd); |
268 closewritefd(channel); | 270 closereadfd(channel, channel->errfd); |
269 } | 271 } |
270 } | 272 } |
271 | 273 |
272 if (!channel->senteof | 274 if (!channel->senteof |
273 && channel->readfd == FD_CLOSED | 275 && channel->readfd == FD_CLOSED |
274 && (channel->extrabuf != NULL || channel->errfd == FD_CLOSED)) { | 276 && (channel->extrabuf == NULL || channel->errfd == FD_CLOSED)) { |
275 send_msg_channel_eof(channel); | 277 send_msg_channel_eof(channel); |
276 } | 278 } |
277 | 279 |
278 if (channel->writefd == FD_CLOSED | 280 if (!channel->sentclosed |
279 && channel->readfd == FD_CLOSED | 281 && channel->writefd == FD_CLOSED |
280 && (channel->extrabuf != NULL || channel->errfd == FD_CLOSED)) { | 282 && channel->readfd == FD_CLOSED |
281 send_msg_channel_close(channel); | 283 && (channel->extrabuf == NULL || channel->errfd == FD_CLOSED)) { |
282 } | 284 send_msg_channel_close(channel); |
283 } | 285 } |
284 | 286 |
285 /* When either party wishes to terminate the channel, it sends | 287 /* When either party wishes to terminate the channel, it sends |
286 * SSH_MSG_CHANNEL_CLOSE. Upon receiving this message, a party MUST | 288 * SSH_MSG_CHANNEL_CLOSE. Upon receiving this message, a party MUST |
287 * send back a SSH_MSG_CHANNEL_CLOSE unless it has already sent this | 289 * send back a SSH_MSG_CHANNEL_CLOSE unless it has already sent this |
442 if (channel->extrabuf == NULL && channel->errfd >= 0) { | 444 if (channel->extrabuf == NULL && channel->errfd >= 0) { |
443 FD_SET(channel->errfd, readfds); | 445 FD_SET(channel->errfd, readfds); |
444 } | 446 } |
445 } | 447 } |
446 | 448 |
447 /* For checking FD status (ie closure etc) - we don't actually | |
448 * read data from writefd */ | |
449 TRACE(("writefd = %d, readfd %d, errfd %d, bufused %d", | 449 TRACE(("writefd = %d, readfd %d, errfd %d, bufused %d", |
450 channel->writefd, channel->readfd, | 450 channel->writefd, channel->readfd, |
451 channel->errfd, | 451 channel->errfd, |
452 cbuf_getused(channel->writebuf) )) | 452 cbuf_getused(channel->writebuf) )) |
453 if (channel->writefd >= 0 && channel->writefd != channel->readfd) { | 453 |
454 /* For checking FD status (ie closure etc) - we don't actually | |
455 * read data from writefd. We don't want to do this for the client, | |
456 * since redirection to /dev/null will make it spin in the select */ | |
457 if (IS_DROPBEAR_SERVER && channel->writefd >= 0 | |
458 && channel->writefd != channel->readfd) { | |
454 FD_SET(channel->writefd, readfds); | 459 FD_SET(channel->writefd, readfds); |
455 } | 460 } |
456 | 461 |
457 /* Stuff from the wire, to local program/shell/user etc */ | 462 /* Stuff from the wire */ |
458 if ((channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0 ) | 463 if ((channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0 ) |
459 || channel->initconn) { | 464 || channel->initconn) { |
460 | |
461 FD_SET(channel->writefd, writefds); | 465 FD_SET(channel->writefd, writefds); |
462 } | 466 } |
463 | 467 |
464 if (channel->extrabuf != NULL && channel->errfd >= 0 | 468 if (channel->extrabuf != NULL && channel->errfd >= 0 |
465 && cbuf_getused(channel->extrabuf) > 0 ) { | 469 && cbuf_getused(channel->extrabuf) > 0 ) { |