1#include "TcpStream.h" 2#include "InetAddress.h" 3 4#include <errno.h> 5#include <signal.h> 6#include <unistd.h> 7#include <sys/socket.h> 8 9namespace 10{ 11 12class IgnoreSigPipe 13{ 14 public: 15 IgnoreSigPipe() 16 { 17 ::signal(SIGPIPE, SIG_IGN); 18 } 19} initObj; 20 21bool isSelfConnection(const Socket& sock) 22{ 23 return sock.getLocalAddr() == sock.getPeerAddr(); 24} 25 26} 27 28TcpStream::TcpStream(Socket&& sock) 29 : sock_(std::move(sock)) 30{ 31} 32 33int TcpStream::receiveAll(void* buf, int len) 34{ 35#ifdef TEMP_FAILURE_RETRY 36 return TEMP_FAILURE_RETRY(::recv(sock_.fd(), buf, len, MSG_WAITALL)); 37#else 38 return ::recv(sock_.fd(), buf, len, MSG_WAITALL); 39#endif 40} 41 42int TcpStream::receiveSome(void* buf, int len) 43{ 44 return sock_.recv(buf, len); 45} 46 47int TcpStream::sendAll(const void* buf, int len) 48{ 49 int written = 0; 50 while (written < len) 51 { 52 int nw = sock_.send(static_cast<const char*>(buf) + written, len - written); 53 if (nw > 0) 54 { 55 written += nw; 56 } 57 else 58 { 59 break; 60 } 61 } 62 return written; 63} 64 65int TcpStream::sendSome(const void* buf, int len) 66{ 67 return sock_.send(buf, len); 68} 69 70void TcpStream::setTcpNoDelay(bool on) 71{ 72 sock_.setTcpNoDelay(on); 73} 74 75void TcpStream::shutdownWrite() 76{ 77 sock_.shutdownWrite(); 78} 79 80TcpStreamPtr TcpStream::connect(const InetAddress& serverAddr) 81{ 82 return connectInternal(serverAddr, nullptr); 83} 84 85TcpStreamPtr TcpStream::connect(const InetAddress& serverAddr, const InetAddress& localAddr) 86{ 87 return connectInternal(serverAddr, &localAddr); 88} 89 90TcpStreamPtr TcpStream::connectInternal(const InetAddress& serverAddr, const InetAddress* localAddr) 91{ 92 TcpStreamPtr stream; 93 Socket sock(Socket::createTCP(serverAddr.family())); 94 if (localAddr) 95 { 96 sock.bindOrDie(*localAddr); 97 } 98 if (sock.connect(serverAddr) == 0 && !isSelfConnection(sock)) 99 { 100 // FIXME: do poll(POLLOUT) to check errors 101 stream.reset(new TcpStream(std::move(sock))); 102 } 103 return stream; 104} 105