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