📄 read_write.c
字号:
#include "common.h"/* Read from the keyboard and write to the server Read from the server and write to the keyboard we use select() to multiplex*/void read_write(ssl,sock) SSL *ssl; { int width; int r,c2sl=0,c2s_offset=0; int read_blocked_on_write=0,write_blocked_on_read=0,read_blocked=0; fd_set readfds,writefds; int shutdown_wait=0; char c2s[BUFSIZZ],s2c[BUFSIZZ]; int ofcmode; /*First we make the socket nonblocking*/ ofcmode=fcntl(sock,F_GETFL,0); ofcmode|=O_NDELAY; if(fcntl(sock,F_SETFL,ofcmode)) err_exit("Couldn't make socket nonblocking"); width=sock+1; while(1){ FD_ZERO(&readfds); FD_ZERO(&writefds); FD_SET(sock,&readfds); /* If we're waiting for a read on the socket don't try to write to the server */ if(!write_blocked_on_read){ /* If we have data in the write queue don't try to read from stdin */ if(c2sl || read_blocked_on_write) FD_SET(sock,&writefds); else FD_SET(fileno(stdin),&readfds); } r=select(width,&readfds,&writefds,0,0); if(r==0) continue; /* Now check if there's data to read */ if((FD_ISSET(sock,&readfds) && !write_blocked_on_read) || (read_blocked_on_write && FD_ISSET(sock,&writefds))){ do { read_blocked_on_write=0; read_blocked=0; r=SSL_read(ssl,s2c,BUFSIZZ); switch(SSL_get_error(ssl,r)){ case SSL_ERROR_NONE: /* Note: this call could block, which blocks the entire application. It's arguable this is the right behavior since this is essentially a terminal client. However, in some other applications you would have to prevent this condition */ fwrite(s2c,1,r,stdout); break; case SSL_ERROR_ZERO_RETURN: /* End of data */ if(!shutdown_wait) SSL_shutdown(ssl); goto end; break; case SSL_ERROR_WANT_READ: read_blocked=1; break; /* We get a WANT_WRITE if we're trying to rehandshake and we block on a write during that rehandshake. We need to wait on the socket to be writeable but reinitiate the read when it is */ case SSL_ERROR_WANT_WRITE: read_blocked_on_write=1; break; default: berr_exit("SSL read problem"); } /* We need a check for read_blocked here because SSL_pending() doesn't work properly during the handshake. This check prevents a busy-wait loop around SSL_read() */ } while (SSL_pending(ssl) && !read_blocked); } /* Check for input on the console*/ if(FD_ISSET(fileno(stdin),&readfds)){ c2sl=read(fileno(stdin),c2s,BUFSIZZ); if(c2sl==0){ shutdown_wait=1; if(SSL_shutdown(ssl)) return; } c2s_offset=0; } /* If the socket is writeable... */ if((FD_ISSET(sock,&writefds) && c2sl) || (write_blocked_on_read && FD_ISSET(sock,&readfds))) { write_blocked_on_read=0; /* Try to write */ r=SSL_write(ssl,c2s+c2s_offset,c2sl); switch(SSL_get_error(ssl,r)){ /* We wrote something*/ case SSL_ERROR_NONE: c2sl-=r; c2s_offset+=r; break; /* We would have blocked */ case SSL_ERROR_WANT_WRITE: break; /* We get a WANT_READ if we're trying to rehandshake and we block on write during the current connection. We need to wait on the socket to be readable but reinitiate our write when it is */ case SSL_ERROR_WANT_READ: write_blocked_on_read=1; break; /* Some other error */ default: berr_exit("SSL write problem"); } } } end: SSL_free(ssl); close(sock); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -