1f41285cfSShuo Chen#include "Acceptor.h" 2f41285cfSShuo Chen#include "InetAddress.h" 3f41285cfSShuo Chen#include "TcpStream.h" 4f41285cfSShuo Chen 5f41285cfSShuo Chen#include <thread> 6f41285cfSShuo Chen 7f41285cfSShuo Chen#include <string.h> 8f41285cfSShuo Chen#include <unistd.h> 9f41285cfSShuo Chen 10f41285cfSShuo Chenint write_n(int fd, const void* buf, int length) 11f41285cfSShuo Chen{ 12f41285cfSShuo Chen int written = 0; 13f41285cfSShuo Chen while (written < length) 14f41285cfSShuo Chen { 15f41285cfSShuo Chen int nw = ::write(fd, static_cast<const char*>(buf) + written, length - written); 16f41285cfSShuo Chen if (nw > 0) 17f41285cfSShuo Chen { 18f41285cfSShuo Chen written += nw; 19f41285cfSShuo Chen } 20f41285cfSShuo Chen else if (nw == 0) 21f41285cfSShuo Chen { 2228d3a254SShuo Chen break; // EOF 23f41285cfSShuo Chen } 24f41285cfSShuo Chen else if (errno != EINTR) 25f41285cfSShuo Chen { 26f41285cfSShuo Chen perror("write"); 27f41285cfSShuo Chen break; 28f41285cfSShuo Chen } 29f41285cfSShuo Chen } 30f41285cfSShuo Chen return written; 31f41285cfSShuo Chen} 32f41285cfSShuo Chen 33f41285cfSShuo Chenvoid run(TcpStreamPtr stream) 34f41285cfSShuo Chen{ 3528d3a254SShuo Chen // Caution: a bad example for closing connection 36f41285cfSShuo Chen std::thread thr([&stream] () { 37f41285cfSShuo Chen char buf[8192]; 38f41285cfSShuo Chen int nr = 0; 39f41285cfSShuo Chen while ( (nr = stream->receiveSome(buf, sizeof(buf))) > 0) 40f41285cfSShuo Chen { 41f41285cfSShuo Chen int nw = write_n(STDOUT_FILENO, buf, nr); 42f41285cfSShuo Chen if (nw < nr) 43f41285cfSShuo Chen { 44f41285cfSShuo Chen break; 45f41285cfSShuo Chen } 46f41285cfSShuo Chen } 4728d3a254SShuo Chen ::exit(0); // should somehow notify main thread instead 48f41285cfSShuo Chen }); 49f41285cfSShuo Chen 50f41285cfSShuo Chen char buf[8192]; 51f41285cfSShuo Chen int nr = 0; 52f41285cfSShuo Chen while ( (nr = ::read(STDIN_FILENO, buf, sizeof(buf))) > 0) 53f41285cfSShuo Chen { 54f41285cfSShuo Chen int nw = stream->sendAll(buf, nr); 55f41285cfSShuo Chen if (nw < nr) 56f41285cfSShuo Chen { 57f41285cfSShuo Chen break; 58f41285cfSShuo Chen } 59f41285cfSShuo Chen } 6028d3a254SShuo Chen stream->shutdownWrite(); 6128d3a254SShuo Chen thr.join(); 62f41285cfSShuo Chen} 63f41285cfSShuo Chen 64f41285cfSShuo Chenint main(int argc, const char* argv[]) 65f41285cfSShuo Chen{ 66f41285cfSShuo Chen if (argc < 3) 67f41285cfSShuo Chen { 68f41285cfSShuo Chen printf("Usage:\n %s hostname port\n %s -l port\n", argv[0], argv[0]); 69f41285cfSShuo Chen return 0; 70f41285cfSShuo Chen } 71f41285cfSShuo Chen 72f41285cfSShuo Chen int port = atoi(argv[2]); 73f41285cfSShuo Chen if (strcmp(argv[1], "-l") == 0) 74f41285cfSShuo Chen { 752de24e35SShuo Chen std::unique_ptr<Acceptor> acceptor(new Acceptor(InetAddress(port))); 762de24e35SShuo Chen TcpStreamPtr stream(acceptor->accept()); 77f41285cfSShuo Chen if (stream) 78f41285cfSShuo Chen { 792de24e35SShuo Chen acceptor.reset(); // stop listening 80f41285cfSShuo Chen run(std::move(stream)); 81f41285cfSShuo Chen } 82f41285cfSShuo Chen else 83f41285cfSShuo Chen { 84f41285cfSShuo Chen perror("accept"); 85f41285cfSShuo Chen } 86f41285cfSShuo Chen } 87f41285cfSShuo Chen else 88f41285cfSShuo Chen { 8924ca08a8SShuo Chen InetAddress addr; 90f41285cfSShuo Chen const char* hostname = argv[1]; 9124ca08a8SShuo Chen if (InetAddress::resolve(hostname, port, &addr)) 92f41285cfSShuo Chen { 93f41285cfSShuo Chen TcpStreamPtr stream(TcpStream::connect(addr)); 94f41285cfSShuo Chen if (stream) 95f41285cfSShuo Chen { 96f41285cfSShuo Chen run(std::move(stream)); 97f41285cfSShuo Chen } 98f41285cfSShuo Chen else 99f41285cfSShuo Chen { 100f41285cfSShuo Chen printf("Unable to connect %s\n", addr.toIpPort().c_str()); 101f41285cfSShuo Chen perror(""); 102f41285cfSShuo Chen } 103f41285cfSShuo Chen } 104f41285cfSShuo Chen else 105f41285cfSShuo Chen { 106f41285cfSShuo Chen printf("Unable to resolve %s\n", hostname); 107f41285cfSShuo Chen } 108f41285cfSShuo Chen } 109f41285cfSShuo Chen} 110