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