xref: /haiku/src/add-ons/print/transports/shared/Socket.cpp (revision 7749d0bb0c358a3279b1b9cc76d8376e900130a5)
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 
25 Socket::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 
36 Socket::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 
47 Socket::~Socket()
48 {
49 	close();
50 	if (__is) {
51 		delete __is;
52 	}
53 	if (__os) {
54 		delete __os;
55 	}
56 }
57 
58 istream &Socket::getInputStream()
59 {
60 	if (__is == NULL) {
61 		__is = new isocketstream(this);
62 	}
63 	return *__is;
64 }
65 
66 ostream &Socket::getOutputStream()
67 {
68 	if (__os == NULL) {
69 		__os = new osocketstream(this);
70 	}
71 	return *__os;
72 }
73 
74 void 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 
123 void Socket::close()
124 {
125 	if (__sock != -1) {
126 		::shutdown(__sock, 2);
127 		::close(__sock);
128 		__sock = -1;
129 	}
130 }
131 
132 bool Socket::fail() const
133 {
134 	return __sock == -1 || __error;
135 }
136 
137 bool Socket::good() const
138 {
139 	return !fail();
140 }
141 
142 bool Socket::operator !() const
143 {
144 	return fail();
145 }
146 
147 int 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 
162 int 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