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