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