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