1 // Sun, 18 Jun 2000 2 // Y.Takagi 3 4 #ifdef __HAIKU__ 5 # include <sys/socket.h> 6 #else 7 # include <net/socket.h> 8 #endif 9 #include <netdb.h> 10 #include <arpa/inet.h> 11 12 #include <stdio.h> 13 #include <unistd.h> 14 15 #include "Socket.h" 16 #include "SocketStream.h" 17 18 #ifndef INADDR_NONE 19 #define INADDR_NONE 0xffffffff 20 #endif 21 22 #include <errno.h> 23 24 Socket::Socket(const char *host, int port) 25 : __sock(-1), __is(NULL), __os(NULL), __error(false) 26 { 27 __host = host; 28 __port = port; 29 __localPort = -1; 30 __error_msg[0] = '\0'; 31 32 open(); 33 } 34 35 Socket::Socket(const char *host, int port, int localPort) 36 : __sock(-1), __is(NULL), __os(NULL), __error(false) 37 { 38 __host = host; 39 __port = port; 40 __localPort = localPort; 41 __error_msg[0] = '\0'; 42 43 open(); 44 } 45 46 Socket::~Socket() 47 { 48 close(); 49 if (__is) { 50 delete __is; 51 } 52 if (__os) { 53 delete __os; 54 } 55 } 56 57 istream &Socket::getInputStream() 58 { 59 if (__is == NULL) { 60 __is = new isocketstream(this); 61 } 62 return *__is; 63 } 64 65 ostream &Socket::getOutputStream() 66 { 67 if (__os == NULL) { 68 __os = new osocketstream(this); 69 } 70 return *__os; 71 } 72 73 void Socket::open() 74 { 75 if (__sock == -1 && !__error) { 76 77 sockaddr_in sin; 78 memset(&sin, 0, sizeof(sin)); 79 80 unsigned long inaddr; 81 hostent *host_info; 82 83 if ((inaddr = inet_addr(__host.c_str())) != INADDR_NONE) { 84 memcpy(&sin.sin_addr, &inaddr, sizeof(inaddr)); 85 sin.sin_family = AF_INET; 86 } else if ((host_info = gethostbyname(__host.c_str())) != NULL) { 87 memcpy(&sin.sin_addr, host_info->h_addr, host_info->h_length); 88 sin.sin_family = host_info->h_addrtype; 89 } else { 90 sprintf(__error_msg, "gethostbyname failed. errno = %d", errno); 91 __error = true; 92 return; 93 } 94 95 if ((__sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 96 sprintf(__error_msg, "socket failed. errno = %d", errno); 97 __error = true; 98 } else { 99 if (__localPort >= 0) { 100 sockaddr_in cin; 101 memset(&cin, 0, sizeof(cin)); 102 cin.sin_family = AF_INET; 103 cin.sin_port = htons(__localPort); 104 if (::bind(__sock, (sockaddr *)&cin, sizeof(cin)) != 0) { 105 sprintf(__error_msg, "bind failed. errno = %d", errno); 106 ::close(__sock); 107 __sock = -1; 108 __error = true; 109 } 110 } 111 sin.sin_port = htons(__port); 112 if (::connect(__sock, (sockaddr *)&(sin), sizeof(sin)) != 0) { 113 sprintf(__error_msg, "connect failed. errno = %d", errno); 114 ::close(__sock); 115 __sock = -1; 116 __error = true; 117 } 118 } 119 } 120 } 121 122 void Socket::close() 123 { 124 if (__sock != -1) { 125 ::shutdown(__sock, 2); 126 ::close(__sock); 127 __sock = -1; 128 } 129 } 130 131 bool Socket::fail() const 132 { 133 return __sock == -1 || __error; 134 } 135 136 bool Socket::good() const 137 { 138 return !fail(); 139 } 140 141 bool Socket::operator !() const 142 { 143 return fail(); 144 } 145 146 int Socket::read(char *buffer, int size, int flags) 147 { 148 if (fail()) { 149 size = 0; 150 } else { 151 size = ::recv(__sock, buffer, size, flags); 152 if (size <= 0) { 153 sprintf(__error_msg, "recv failed. errno = %d", errno); 154 __error = true; 155 close(); 156 } 157 } 158 return size; 159 } 160 161 int Socket::write(const char *buffer, int size, int flags) 162 { 163 if (fail()) { 164 size = 0; 165 } else { 166 size = ::send(__sock, buffer, size, flags); 167 if (size <= 0) { 168 sprintf(__error_msg, "send failed. errno = %d", errno); 169 __error = true; 170 close(); 171 } 172 } 173 return size; 174 } 175