xref: /haiku/src/add-ons/print/transports/shared/Socket.cpp (revision 302f62604763c95777d6d04cca456e876f471c4f)
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