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