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