xref: /haiku/src/kits/network/libnetapi/NetEndpoint.cpp (revision fef6144999c2fa611f59ee6ffe6dd7999501385c)
1 /******************************************************************************
2 /
3 /	File:			NetEndpoint.cpp
4 /
5 /   Description:    The Network API.
6 /
7 /	Copyright 2002, OpenBeOS Project, All Rights Reserved.
8 /
9 ******************************************************************************/
10 
11 #include <string.h>
12 #include <sys/time.h>
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <netinet/in.h>
16 #include <netdb.h>
17 #include <fcntl.h>
18 #include <unistd.h>
19 #include <errno.h>
20 
21 #include <Message.h>
22 #include <NetEndpoint.h>
23 
24 
25 BNetEndpoint::BNetEndpoint(int protocol)
26 	:	m_init(B_NO_INIT), m_socket(-1), m_timeout(B_INFINITE_TIMEOUT), m_last_error(0)
27 {
28 	if ((m_socket = socket(AF_INET, protocol, 0)) < 0)
29 		m_last_error = errno;
30 	else
31 		m_init = B_OK;
32 }
33 
34 
35 BNetEndpoint::BNetEndpoint(int family, int type, int protocol)
36 	:	m_init(B_NO_INIT), m_socket(-1), m_timeout(B_INFINITE_TIMEOUT), m_last_error(0)
37 {
38 	if ((m_socket = socket(family, type, protocol)) < 0)
39 		m_last_error = errno;
40 	else
41 		m_init = B_OK;
42 }
43 
44 
45 BNetEndpoint::BNetEndpoint(BMessage *archive)
46 	:	m_init(B_NO_INIT),
47 		m_socket(-1),
48 		m_timeout(B_INFINITE_TIMEOUT),
49 		m_last_error(0)
50 {
51 	// TODO
52 	if (! archive)
53 		return;
54 
55 	BMessage msg;
56 
57 	if (archive->FindMessage("bnendp_peer", &msg) != B_OK)
58 		return;
59 	m_peer = BNetAddress(&msg);
60 
61 	if (archive->FindMessage("bnendp_addr", &msg) != B_OK)
62 		return;
63 	m_addr = BNetAddress(&msg);
64 
65 	if (archive->FindMessage("bnendp_conaddr", &msg) != B_OK)
66 		return;
67 	m_conaddr = BNetAddress(&msg);
68 
69 	m_init = B_OK;
70 }
71 
72 
73 BNetEndpoint::BNetEndpoint(const BNetEndpoint & ep)
74 	:	m_init(ep.m_init), m_timeout(ep.m_timeout),	m_last_error(ep.m_last_error),
75 		m_addr(ep.m_addr), m_peer(ep.m_peer)
76 {
77 	m_socket = -1;
78 	if (ep.m_socket >= 0)
79 		m_socket = dup(ep.m_socket);
80 }
81 
82 
83 BNetEndpoint & BNetEndpoint::operator=(const BNetEndpoint & ep)
84 {
85 	Close();
86 
87 	m_init 			= ep.m_init;
88 	m_timeout 		= ep.m_timeout;
89 	m_last_error	= ep.m_last_error;
90 	m_addr			= ep.m_addr;
91 	m_peer			= ep.m_peer;
92 
93 	m_socket = -1;
94 	if (ep.m_socket >= 0)
95 		m_socket = dup(ep.m_socket);
96 
97 	if (m_socket >= 0)
98 		m_init = B_OK;
99 
100     return *this;
101 }
102 
103 BNetEndpoint::~BNetEndpoint()
104 {
105 	Close();
106 }
107 
108 // #pragma mark -
109 
110 status_t BNetEndpoint::Archive(BMessage *into, bool deep = true) const
111 {
112 	// TODO
113 
114 	if( into == 0 )
115 		return B_ERROR;
116 
117 	if ( m_init != B_OK )
118 		return B_NO_INIT;
119 
120 	BMessage msg;
121 
122 	if (m_peer.Archive(&msg) != B_OK)
123 		return B_ERROR;
124 	if (into->AddMessage("bnendp_peer", &msg) != B_OK)
125 		return B_ERROR;
126 
127 	if (m_addr.Archive(&msg) != B_OK)
128 		return B_ERROR;
129 	if (into->AddMessage("bnendp_addr", &msg) != B_OK)
130 		return B_ERROR;
131 
132 	if (m_conaddr.Archive(&msg) != B_OK)
133 		return B_ERROR;
134 	if (into->AddMessage("bnendp_conaddr", &msg) != B_OK)
135 		return B_ERROR;
136 
137 	return B_OK;
138 }
139 
140 
141 BArchivable *BNetEndpoint::Instantiate(BMessage *archive)
142 {
143 	if (! archive)
144 		return NULL;
145 
146 	if (! validate_instantiation(archive, "BNetAddress") )
147 		return NULL;
148 
149 	BNetEndpoint *ep = new BNetEndpoint(archive);
150 	if (ep && ep->InitCheck() == B_OK)
151 		return ep;
152 
153 	delete ep;
154 	return NULL;
155 }
156 
157 // #pragma mark -
158 
159 
160 status_t BNetEndpoint::InitCheck()
161 {
162 	return m_init;
163 }
164 
165 
166 int BNetEndpoint::Socket() const
167 {
168 	return m_socket;
169 }
170 
171 
172 const BNetAddress & BNetEndpoint::LocalAddr()
173 {
174 	return m_addr;
175 }
176 
177 
178 const BNetAddress & BNetEndpoint::RemoteAddr()
179 {
180 	return m_peer;
181 }
182 
183 
184 status_t BNetEndpoint::SetProtocol(int protocol)
185 {
186 	Close();
187 	if ((m_socket = socket(AF_INET, protocol, 0)) < 0) {
188 		m_last_error = errno;
189 		return m_last_error;
190 	}
191 	m_init = B_OK;
192 	return m_init;
193 }
194 
195 
196 int BNetEndpoint::SetOption(int32 option, int32 level,
197 							 	 const void * data, unsigned int length)
198 {
199 	if (m_socket < 0)
200 		return B_ERROR;
201 
202 	if (setsockopt(m_socket, level, option, data, length) < 0) {
203 		m_last_error = errno;
204 		return B_ERROR;
205 	}
206 	return B_OK;
207 }
208 
209 
210 int BNetEndpoint::SetNonBlocking(bool enable)
211 {
212 	int flags = fcntl(m_socket, F_GETFL);
213 
214 	if (enable)
215 		flags |= O_NONBLOCK;
216 	else
217 		flags &= ~O_NONBLOCK;
218 
219 	if (fcntl(m_socket, F_SETFL, flags) < 0) {
220 		m_last_error = errno;
221 		return B_ERROR;
222 	}
223 
224 	return B_OK;
225 }
226 
227 
228 int BNetEndpoint::SetReuseAddr(bool enable)
229 {
230 	int onoff = (int) enable;
231 	return SetOption(SO_REUSEADDR, SOL_SOCKET, &onoff, sizeof(onoff));
232 }
233 
234 
235 void BNetEndpoint::SetTimeout(bigtime_t timeout)
236 {
237 	m_timeout = timeout;
238 }
239 
240 
241 int BNetEndpoint::Error() const
242 {
243 	return m_last_error;
244 }
245 
246 
247 char * BNetEndpoint::ErrorStr() const
248 {
249 	return strerror(m_last_error);
250 }
251 
252 
253 // #pragma mark -
254 
255 void BNetEndpoint::Close()
256 {
257 	if (m_socket >= 0)
258 		close(m_socket);
259 	m_socket = -1;
260 	m_init = B_NO_INIT;
261 }
262 
263 
264 status_t BNetEndpoint::Bind(const BNetAddress & address)
265 {
266 	struct sockaddr_in addr;
267 	status_t status;
268 
269 	status = address.GetAddr(addr);
270 	if (status != B_OK)
271 		return status;
272 
273 	if (bind(m_socket, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
274 		m_last_error = errno;
275 		Close();
276 		return B_ERROR;
277 	}
278 
279 	int sz = sizeof(addr);
280 
281 	if (getsockname(m_socket, (struct sockaddr *) &addr, &sz) < 0) {
282 		m_last_error = errno;
283 		Close();
284 		return B_ERROR;
285 	}
286 
287 #ifdef _NETDB_H_
288 	if (addr.sin_addr.s_addr == 0) {
289 		// Grrr, buggy getsockname!
290 		char hostname[MAXHOSTNAMELEN];
291 		struct hostent *he;
292 		gethostname(hostname, sizeof(hostname));
293 		he = gethostbyname(hostname);
294 		if (he)
295 			memcpy(&addr.sin_addr.s_addr, he->h_addr, sizeof(addr.sin_addr.s_addr));
296 	}
297 #endif
298 	m_addr.SetTo(addr);
299 	return B_OK;
300 }
301 
302 
303 status_t BNetEndpoint::Bind(int port)
304 {
305 	BNetAddress addr(INADDR_ANY, port);
306 	return Bind(addr);
307 }
308 
309 
310 status_t BNetEndpoint::Connect(const BNetAddress & address)
311 {
312 	sockaddr_in addr;
313 
314 	if (address.GetAddr(addr) != B_OK)
315 		return B_ERROR;
316 
317 	if (connect(m_socket, (sockaddr *) &addr, sizeof(addr)) < 0) {
318 		Close();
319 		m_last_error = errno;
320 		return B_ERROR;
321 	}
322 
323 	int sz = sizeof(addr);
324 	if (getpeername(m_socket, (sockaddr *) &addr, &sz) < 0) {
325 		Close();
326 		return B_ERROR;
327 	}
328 
329 	m_peer.SetTo(addr);
330 	return B_OK;
331 }
332 
333 
334 status_t BNetEndpoint::Connect(const char *hostname, int port)
335 {
336 	BNetAddress addr(hostname, port);
337 	return Connect(addr);
338 }
339 
340 
341 status_t BNetEndpoint::Listen(int backlog)
342 {
343 	if (listen(m_socket, backlog) < 0) {
344 		Close();
345 		m_last_error = errno;
346 		return B_ERROR;
347 	}
348 	return B_OK;
349 }
350 
351 
352 BNetEndpoint * BNetEndpoint::Accept(int32 timeout)
353 {
354 	if (! IsDataPending(timeout < 0 ? B_INFINITE_TIMEOUT : 1000LL * timeout))
355 		return NULL;
356 
357 	struct sockaddr_in addr;
358 	int sz = sizeof(addr);
359 
360 	int handle = accept(m_socket, (struct sockaddr *) &addr, &sz);
361 	if (handle < 0) {
362 		Close();
363 		m_last_error = errno;
364 		return NULL;
365 	}
366 
367 	BNetEndpoint * ep = new BNetEndpoint(*this);
368 	if (! ep) {
369 		close(handle);
370 		return NULL;
371 	}
372 
373 	ep->m_socket = handle;
374 	ep->m_peer.SetTo(addr);
375 	if (getsockname(handle, (struct sockaddr *) &addr, &sz) < 0) {
376 		ep->Close();
377 		delete ep;
378 		return NULL;
379 	}
380 
381 	ep->m_addr.SetTo(addr);
382 	return ep;
383 }
384 
385 // #pragma mark -
386 
387 bool BNetEndpoint::IsDataPending(bigtime_t timeout)
388 {
389 	fd_set fds;
390 	struct timeval tv, *tv_ptr = NULL;
391 
392 	FD_ZERO(&fds);
393 	FD_SET(m_socket, &fds);
394 
395 	if (timeout > 0) {
396 		tv.tv_sec = timeout / 1000000;
397 		tv.tv_usec = (timeout % 1000000);
398 		tv_ptr = &tv;
399 	}
400 
401 	if (select(m_socket + 1, &fds, NULL, NULL, &tv) < 0) {
402 		m_last_error = errno;
403 		return false;
404 	}
405 
406 	return FD_ISSET(m_socket, &fds);
407 }
408 
409 
410 int32 BNetEndpoint::Receive(void * buffer, size_t length, int flags)
411 {
412 	if (m_timeout >= 0 && IsDataPending(m_timeout) == false)
413 		return 0;
414 
415 	ssize_t sz = recv(m_socket, buffer, length, flags);
416 	if (sz < 0)
417 		m_last_error = errno;
418 	return sz;
419 }
420 
421 
422 int32 BNetEndpoint::Receive(BNetBuffer & buffer, size_t length, int flags)
423 {
424 	BNetBuffer chunk(length);
425 	length = Receive(chunk.Data(), length, flags);
426 	buffer.AppendData(chunk.Data(), length);
427 	return length;
428 }
429 
430 
431 int32 BNetEndpoint::ReceiveFrom(void * buffer, size_t length,
432 							    BNetAddress & address, int flags)
433 {
434 	if (m_timeout >= 0 && IsDataPending(m_timeout) == false)
435 		return 0;
436 
437 	struct sockaddr_in addr;
438 	int sz = sizeof(addr);
439 
440 	length = recvfrom(m_socket, buffer, length, flags,
441 						(struct sockaddr *) &addr, &sz);
442 	if (length < 0)
443 		m_last_error = errno;
444 	else
445 		address.SetTo(addr);
446 	return length;
447 }
448 
449 
450 int32 BNetEndpoint::ReceiveFrom(BNetBuffer & buffer, size_t length,
451 							    BNetAddress & address, int flags)
452 {
453 	BNetBuffer chunk(length);
454 	length = ReceiveFrom(chunk.Data(), length, address, flags);
455 	buffer.AppendData(chunk.Data(), length);
456 	return length;
457 }
458 
459 
460 int32 BNetEndpoint::Send(const void * buffer, size_t length, int flags)
461 {
462 	ssize_t sz;
463 
464 	sz = send(m_socket, (const char *) buffer, length, flags);
465 	if (sz < 0)
466 		m_last_error = errno;
467 	return sz;
468 }
469 
470 
471 int32 BNetEndpoint::Send(BNetBuffer & buffer, int flags)
472 {
473 	return Send(buffer.Data(), buffer.Size(), flags);
474 }
475 
476 
477 int32 BNetEndpoint::SendTo(const void * buffer, size_t length,
478 						   const BNetAddress & address, int flags)
479 {
480 	ssize_t	sz;
481 	struct sockaddr_in addr;
482 
483 	if (address.GetAddr(addr) != B_OK)
484 		return B_ERROR;
485 
486 	sz = sendto(m_socket, buffer, length, flags,
487 				  (struct sockaddr *) &addr, sizeof(addr));
488 	if (sz < 0)
489 		m_last_error = errno;
490 	return sz;
491 }
492 
493 int32 BNetEndpoint::SendTo(BNetBuffer & buffer,
494 						   const BNetAddress & address, int flags)
495 {
496 	return SendTo(buffer.Data(), buffer.Size(), address, flags);
497 }
498 
499 // #pragma mark -
500 
501 // These are virtuals, implemented for binary compatibility purpose
502 void BNetEndpoint::_ReservedBNetEndpointFBCCruft1()
503 {
504 }
505 
506 
507 void BNetEndpoint::_ReservedBNetEndpointFBCCruft2()
508 {
509 }
510 
511 
512 void BNetEndpoint::_ReservedBNetEndpointFBCCruft3()
513 {
514 }
515 
516 
517 void BNetEndpoint::_ReservedBNetEndpointFBCCruft4()
518 {
519 }
520 
521 
522 void BNetEndpoint::_ReservedBNetEndpointFBCCruft5()
523 {
524 }
525 
526 
527 void BNetEndpoint::_ReservedBNetEndpointFBCCruft6()
528 {
529 }
530 
531