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 ) {