]> Dogcows Code - chaz/yoink/blob - src/stlplus/portability/ip_sockets.cpp
import stlplus 3.7
[chaz/yoink] / src / stlplus / portability / ip_sockets.cpp
1 ////////////////////////////////////////////////////////////////////////////////
2
3 // Author: Andy Rushton
4 // Copyright: (c) Southampton University 1999-2004
5 // (c) Andy Rushton 2004 onwards
6 // License: BSD License, see ../docs/license.html
7
8 // Contains all the platform-specific socket handling used by the TCP and UDP classes
9
10 // TODO - any conversion required to support IPv6
11
12 ////////////////////////////////////////////////////////////////////////////////
13
14 #include "ip_sockets.hpp"
15 #include "dprintf.hpp"
16 #include <string.h>
17
18 #ifdef MSWINDOWS
19 // Windoze-specific includes
20 #include <winsock2.h>
21 #define ERRNO WSAGetLastError()
22 #define HERRNO WSAGetLastError()
23 #define IOCTL ioctlsocket
24 #define CLOSE closesocket
25 #define SHUT_RDWR SD_BOTH
26 #define SOCKLEN_T int
27 #define SEND_FLAGS 0
28 #if _MSC_VER < 1600 // not defined before Visual Studio 10
29 #define EINPROGRESS WSAEINPROGRESS
30 #define EWOULDBLOCK WSAEWOULDBLOCK
31 #define ECONNRESET WSAECONNRESET
32 #endif
33 #else
34 // Generic Unix includes
35 // fix for older versions of Darwin?
36 #define _BSD_SOCKLEN_T_ int
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <sys/ioctl.h>
40 #include <sys/time.h>
41 #include <netinet/in.h>
42 #include <errno.h>
43 #include <netdb.h>
44 #include <unistd.h>
45 #define INVALID_SOCKET -1
46 #define ERRNO errno
47 #define HERRNO h_errno
48 #define SOCKET int
49 #define SOCKET_ERROR -1
50 #define IOCTL ::ioctl
51 #define CLOSE ::close
52 #define SOCKLEN_T socklen_t
53 #define SEND_FLAGS MSG_NOSIGNAL
54 #ifdef SOLARIS
55 // Sun put some definitions in a different place
56 #include <sys/filio.h>
57 #endif
58 #endif
59
60 ////////////////////////////////////////////////////////////////////////////////
61
62 namespace stlplus
63 {
64
65 ////////////////////////////////////////////////////////////////////////////////
66 // Utilities
67
68 // get an operating-system error message given an error code
69 static std::string error_string(int error)
70 {
71 std::string result = "error " + dformat("%d",error);
72 #ifdef MSWINDOWS
73 char* message = 0;
74 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
75 0,
76 error,
77 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // "User default language"
78 (LPTSTR)&message,
79 0,0);
80 if (message)
81 {
82 result = message;
83 LocalFree(message);
84 }
85 // the error message is for some perverse reason newline terminated - remove this
86 if (result[result.size()-1] == '\n')
87 result.erase(result.end()-1);
88 if (result[result.size()-1] == '\r')
89 result.erase(result.end()-1);
90 #else
91 char* message = strerror(error);
92 if (message && message[0])
93 result = message;
94 #endif
95 return result;
96 }
97
98 // convert address:port into a sockaddr
99 static void convert_address(unsigned long address, unsigned short port, sockaddr& sa)
100 {
101 sa.sa_family = AF_INET;
102 unsigned short network_port = htons(port);
103 memcpy(&sa.sa_data[0], &network_port, sizeof(network_port));
104 unsigned long network_address = htonl(address);
105 memcpy(&sa.sa_data[2], &network_address, sizeof(network_address));
106 }
107
108 // // convert host:port into a sockaddr
109 // static void convert_host(hostent& host, unsigned short port, sockaddr& sa)
110 // {
111 // sa.sa_family = host.h_addrtype;
112 // unsigned short network_port = htons(port);
113 // memcpy(&sa.sa_data[0], &network_port, sizeof(network_port));
114 // memcpy(&sa.sa_data[2], host.h_addr, host.h_length);
115 // }
116
117 // convert sockaddr to address:port
118 static void convert_sockaddr(const sockaddr& sa, unsigned long& address, unsigned short& port)
119 {
120 unsigned short network_port = 0;
121 memcpy(&network_port, &sa.sa_data[0], sizeof(network_port));
122 port = ntohs(network_port);
123 unsigned long network_address = 0;
124 memcpy(&network_address, &sa.sa_data[2], sizeof(network_address));
125 address = ntohl(network_address);
126 }
127
128 ////////////////////////////////////////////////////////////////////////////////
129 // Initialisation
130 // Windows requires that Winsock is initialised before use and closed after
131 // These routines initialise once on first use and close on the destruction of the last object using it
132 // on non-windows platforms, I still increment/decrement the sockets count variable for diagnostic purposes
133
134 static int sockets_count = 0;
135
136 static int sockets_init(void)
137 {
138 int error = 0;
139 if (sockets_count++ == 0)
140 {
141 #ifdef MSWINDOWS
142 WSAData winsock_info;
143 // request Winsock 2.0 or higher
144 error = WSAStartup(MAKEWORD(2,0),&winsock_info);
145 #endif
146 }
147 return error;
148 }
149
150 static int sockets_close(void)
151 {
152 int error = 0;
153 if (--sockets_count == 0)
154 {
155 #ifdef MSWINDOWS
156 if (WSACleanup() == SOCKET_ERROR)
157 error = ERRNO;
158 #endif
159 }
160 return error;
161 }
162
163 ////////////////////////////////////////////////////////////////////////////////
164 // Socket Implementation - common code to manipulate a TCP socket
165
166 class IP_socket_internals
167 {
168 private:
169 IP_socket_type m_type;
170 SOCKET m_socket;
171 unsigned long m_remote_address;
172 unsigned short m_remote_port;
173 mutable int m_error;
174 mutable std::string m_message;
175 unsigned m_count;
176
177 // disable copying of the internals
178 IP_socket_internals(const IP_socket_internals&);
179 IP_socket_internals& operator=(const IP_socket_internals&);
180
181 public:
182
183 ////////////////////////////////////////////////////////////////////////////
184 // PIMPL alias counting
185
186 void increment(void)
187 {
188 ++m_count;
189 }
190
191 bool decrement(void)
192 {
193 --m_count;
194 return m_count == 0;
195 }
196
197 ////////////////////////////////////////////////////////////////////////////
198 // constructors/destructors
199
200 // construct an invalid socket
201 IP_socket_internals(void) : m_type(undefined_socket_type), m_socket(INVALID_SOCKET), m_error(0), m_count(1)
202 {
203 set_error(sockets_init());
204 }
205
206 // close on destroy
207 ~IP_socket_internals(void)
208 {
209 close();
210 set_error(sockets_close());
211 }
212
213 ////////////////////////////////////////////////////////////////////////////
214 // initialisation, connection
215
216 bool initialised(void) const
217 {
218 return m_socket != INVALID_SOCKET;
219 }
220
221 // attach this object to a pre-opened socket
222 bool set(SOCKET socket, unsigned long remote_address, unsigned short remote_port)
223 {
224 if (initialised()) close();
225 clear_error();
226 m_socket = socket;
227 m_remote_address = remote_address;
228 m_remote_port = remote_port;
229 return true;
230 }
231
232 // create a raw socket attached to this object
233 bool initialise(IP_socket_type type)
234 {
235 if (initialised()) close();
236 clear_error();
237 if ((type != TCP) && (type != UDP))
238 {
239 set_error(-1, "Illegal socket type");
240 return false;
241 }
242 // create an anonymous socket
243 m_socket = ::socket(AF_INET, ((type == TCP) ? SOCK_STREAM : SOCK_DGRAM), 0);
244 if (m_socket == INVALID_SOCKET)
245 {
246 set_error(ERRNO);
247 close();
248 return false;
249 }
250 // record the type on success only
251 m_type = type;
252 // set the socket into non-blocking mode
253 unsigned long nonblocking = 1;
254 if (IOCTL(m_socket, FIONBIO, &nonblocking) == SOCKET_ERROR)
255 {
256 set_error(ERRNO);
257 return false;
258 }
259 return true;
260 }
261
262 // function for performing IP lookup (i.e. gethostbyname)
263 // could be standalone but making it a member means that it can use the socket's error handler
264 // - remote_address: IP name or number
265 // - returns the IP address as a number - zero if there's an error
266 unsigned long ip_lookup(const std::string& remote_address)
267 {
268 unsigned long result = 0;
269 // Lookup the IP address to convert it into a host record
270 // this DOES lookup IP address names as well (not according to MS help !!)
271 // TODO - convert this to use ::getaddrinfo - ::gethostbyname is deprecated
272 hostent* host_info = ::gethostbyname(remote_address.c_str());
273 if (!host_info)
274 {
275 set_error(HERRNO);
276 return 0;
277 }
278 // extract the address from the host info
279 unsigned long network_address = 0;
280 memcpy(&network_address, host_info->h_addr, host_info->h_length);
281 result = ntohl(network_address);
282 return result;
283 }
284
285 // tests whether a socket is ready for communication
286 bool select(bool readable, bool writeable, unsigned wait)
287 {
288 if (!initialised()) return false;
289 // set up the readable set
290 fd_set readable_set;
291 fd_set* readable_set_ptr = 0;
292 if (readable)
293 {
294 FD_ZERO(&readable_set);
295 FD_SET(m_socket,&readable_set);
296 readable_set_ptr = &readable_set;
297 }
298 // set up the writeable set
299 fd_set writeable_set;
300 fd_set* writeable_set_ptr = 0;
301 if (writeable)
302 {
303 FD_ZERO(&writeable_set);
304 FD_SET(m_socket,&writeable_set);
305 writeable_set_ptr = &writeable_set;
306 }
307 // TODO - check the error set and lookup the error?
308 fd_set* error_set_ptr = 0;
309 // set up the timout value
310 // Note: a null pointer implements a blocking select
311 // a pointer to a zero value implements a zero-wait poll
312 // a pointer to a positive value implements a poll with a timeout
313 // I currently only implement polling with timeout which may be zero - no blocking
314 timeval timeout;
315 timeval* timeout_ptr = 0;
316 timeout.tv_sec = wait/1000000;
317 timeout.tv_usec = wait%1000000;
318 timeout_ptr = &timeout;
319 // now test the socket
320 int select_result = ::select(m_socket+1, readable_set_ptr, writeable_set_ptr, error_set_ptr, timeout_ptr);
321 switch(select_result)
322 {
323 case SOCKET_ERROR:
324 // select failed with an error - trap the error
325 set_error(ERRNO);
326 return false;
327 case 0:
328 // timeout exceeded without a connection appearing
329 return false;
330 default:
331 // at least one connection is pending
332 // TODO - do we need to do the extra socket options checking on Posix?
333 // TODO - does this connect in any way to the error_set above?
334 return true;
335 }
336 }
337
338 // bind the socket to a port so that it can receive from specific address
339 bool bind(unsigned long remote_address, unsigned short local_port)
340 {
341 if (!initialised()) return false;
342 // name the socket and bind it to a port - this is a requirement for a server
343 sockaddr server;
344 convert_address(INADDR_ANY, local_port, server);
345 if (::bind(m_socket, &server, sizeof(server)) == SOCKET_ERROR)
346 {
347 set_error(ERRNO);
348 close();
349 return false;
350 }
351 return true;
352 }
353
354 // bind the socket to a port so that it can receive from any address
355 bool bind_any(unsigned short local_port)
356 {
357 return bind(INADDR_ANY, local_port);
358 }
359
360 // set this socket up to be a listening port
361 // must have been bound to a local port already
362 // - length of backlog queue to manage - may be zero
363 // - returns success status
364 bool listen(unsigned short queue)
365 {
366 if (!initialised()) return false;
367 // set the port to listen for incoming connections
368 if (::listen(m_socket, (int)queue) == SOCKET_ERROR)
369 {
370 set_error(ERRNO);
371 close();
372 return false;
373 }
374 return true;
375 }
376
377 // test whether there's an incoming connection on the socket
378 // only applicable if it has been set up as a listening port
379 bool accept_ready(unsigned wait)
380 {
381 // the test for a connection being ready is the same as the test for whether the socket is readable
382 // see documentation for select
383 return select(true, false, wait);
384 }
385
386 // accept a connection on the socket
387 // only applicable if it has been set up as a listening port
388 // - returns socket filled in with the accepted connection's details - or with the error fields set
389 IP_socket accept(void)
390 {
391 if (!initialised()) return IP_socket();
392 IP_socket result;
393 // accept the connection, at the same time getting the address of the connecting client
394 sockaddr saddress;
395 SOCKLEN_T saddress_length = sizeof(saddress);
396 SOCKET socket = ::accept(m_socket, &saddress, &saddress_length);
397 if (socket == INVALID_SOCKET)
398 {
399 // only set the result socket with an error
400 result.m_impl->set_error(ERRNO);
401 return result;
402 }
403 // extract the contents of the address
404 unsigned long remote_address = 0;
405 unsigned short remote_port = 0;
406 convert_sockaddr(saddress, remote_address, remote_port);
407 result.m_impl->set(socket, remote_address, remote_port);
408 return result;
409 }
410
411 // client connect to a server
412 // - remote_address: IP number of remote address to connect to
413 // - remote_port: port to connect to
414 bool connect(unsigned long remote_address, unsigned short remote_port)
415 {
416 if (!initialised()) return false;
417 // fill in the connection data structure
418 sockaddr connect_data;
419 convert_address(remote_address, remote_port, connect_data);
420 // connect binds the socket to a local address
421 // if connectionless it simply sets the default remote address
422 // if connectioned it makes the connection
423 if (::connect(m_socket, &connect_data, sizeof(connect_data)) == SOCKET_ERROR)
424 {
425 // the socket is non-blocking, so connect will almost certainly fail with EINPROGRESS which is not an error
426 // only catch real errors
427 int error = ERRNO;
428 if (error != EINPROGRESS && error != EWOULDBLOCK)
429 {
430 set_error(error);
431 return false;
432 }
433 }
434 // extract the remote connection details for local storage
435 convert_sockaddr(connect_data, m_remote_address, m_remote_port);
436 return true;
437 }
438
439 // test whether a socket is connected and ready to communicate
440 bool connected(unsigned wait)
441 {
442 if (!initialised()) return false;
443 // Linux and Windows docs say test with select for whether socket is
444 // writable. However, a problem has been reported with Linux whereby
445 // the OS will report a socket as writable when it isn't
446 // first use the select method
447 if (!select(false, true, wait))
448 return false;
449 #ifdef MSWINDOWS
450 // Windows needs no further processing - select method works
451 return true;
452 #else
453 // Posix version needs further checking using the socket options
454 // DJDM: socket has returned EINPROGRESS on the first attempt at connection
455 // it has also returned that it can be written to
456 // we must now ask it if it has actually connected - using getsockopt
457 int error = 0;
458 socklen_t serror = sizeof(int);
459 if (::getsockopt(m_socket, SOL_SOCKET, SO_ERROR, &error, &serror)==0)
460 // handle the error value - one of them means that the socket has connected
461 if (!error || error == EISCONN)
462 return true;
463 return false;
464 #endif
465 }
466
467 bool close(void)
468 {
469 bool result = true;
470 if (initialised())
471 {
472 if (shutdown(m_socket,SHUT_RDWR) == SOCKET_ERROR)
473 {
474 set_error(ERRNO);
475 result = false;
476 }
477 if (CLOSE(m_socket) == SOCKET_ERROR)
478 {
479 set_error(ERRNO);
480 result = false;
481 }
482 }
483 m_socket = INVALID_SOCKET;
484 m_remote_address = 0;
485 m_remote_port = 0;
486 return result;
487 }
488
489 ////////////////////////////////////////////////////////////////////////////
490 // sending/receiving
491
492 bool send_ready(unsigned wait)
493 {
494 // determines whether the socket is ready to send by testing whether it is writable
495 return select(false, true, wait);
496 }
497
498 bool send (std::string& data)
499 {
500 if (!initialised()) return false;
501 // send the data - this will never block but may not send all the data
502 int bytes = ::send(m_socket, data.c_str(), data.size(), SEND_FLAGS);
503 if (bytes == SOCKET_ERROR)
504 {
505 set_error(ERRNO);
506 return false;
507 }
508 // remove the sent bytes from the data buffer so that the buffer represents the data still to be sent
509 data.erase(0,bytes);
510 return true;
511 }
512
513 bool send_packet(std::string& data, unsigned long address = 0, unsigned short port = 0)
514 {
515 if (!initialised()) return false;
516 // if no address specified, rely on the socket having been connected (can I test this?)
517 // so use the standard send, otherwise use the sendto function
518 int bytes = 0;
519 if (!address)
520 {
521 bytes = ::send(m_socket, data.c_str(), data.size(), SEND_FLAGS);
522 }
523 else
524 {
525 sockaddr saddress;
526 convert_address(address, port, saddress);
527 bytes = ::sendto(m_socket, data.c_str(), data.size(), SEND_FLAGS, &saddress, sizeof(saddress));
528 }
529 if (bytes == SOCKET_ERROR)
530 {
531 set_error(ERRNO);
532 return false;
533 }
534 // remove the sent bytes from the data buffer so that the buffer represents the data still to be sent
535 data.erase(0,bytes);
536 return true;
537 }
538
539 bool receive_ready(unsigned wait)
540 {
541 // determines whether the socket is ready to receive by testing whether it is readable
542 return select(true, false, wait);
543 }
544
545 bool receive (std::string& data)
546 {
547 if (!initialised()) return false;
548 // determine how much data is available to read
549 unsigned long bytes = 0;
550 if (IOCTL(m_socket, FIONREAD, &bytes) == SOCKET_ERROR)
551 {
552 set_error(ERRNO);
553 return false;
554 }
555 // get the data up to the amount claimed to be present - this is non-blocking
556 char* buffer = new char[bytes+1];
557 int read = ::recv(m_socket, buffer, bytes, 0);
558 if (read == SOCKET_ERROR)
559 {
560 delete[] buffer;
561 set_error(ERRNO);
562 close();
563 return false;
564 }
565 if (read == 0)
566 {
567 // TODO - check whether this is an appropriate conditon to close the socket
568 close();
569 }
570 else
571 {
572 // this is binary data so copy the bytes including nulls
573 data.append(buffer,read);
574 }
575 delete[] buffer;
576 return true;
577 }
578
579 bool receive_packet(std::string& data, unsigned long& address, unsigned short& port)
580 {
581 if (!initialised()) return false;
582 // determine how much data is available to read
583 unsigned long bytes = 0;
584 if (IOCTL(m_socket, FIONREAD, &bytes) == SOCKET_ERROR)
585 {
586 set_error(ERRNO);
587 return false;
588 }
589 // get the data up to the amount claimed to be present - this is non-blocking
590 // also get the sender's details
591 char* buffer = new char[bytes+1];
592 sockaddr saddress;
593 SOCKLEN_T saddress_length = sizeof(saddress);
594 int read = ::recvfrom(m_socket, buffer, bytes, 0, &saddress, &saddress_length);
595 if (read == SOCKET_ERROR)
596 {
597 // UDP connection reset means that a previous sent failed to deliver cos the address was unknown
598 // this is NOT an error with the sending server socket, which IS still usable
599 int error = ERRNO;
600 if (error != ECONNRESET)
601 {
602 delete[] buffer;
603 set_error(error);
604 close();
605 return false;
606 }
607 }
608 // this is binary data so copy the bytes including nulls
609 data.append(buffer,read);
610 // also retrieve the sender's details
611 convert_sockaddr(saddress, address, port);
612 delete[] buffer;
613 return true;
614 }
615
616 bool receive_packet(std::string& data)
617 {
618 // call the above and then discard the address details
619 unsigned long address = 0;
620 unsigned short port = 0;
621 return receive_packet(data, address, port);
622 }
623
624 ////////////////////////////////////////////////////////////////////////////
625 // informational
626
627 IP_socket_type type(void) const
628 {
629 return m_type;
630 }
631
632 unsigned short local_port(void) const
633 {
634 if (!initialised()) return 0;
635 sockaddr saddress;
636 SOCKLEN_T saddress_length = sizeof(saddress);
637 if (::getsockname(m_socket, &saddress, &saddress_length) != 0)
638 {
639 set_error(ERRNO);
640 return 0;
641 }
642 unsigned long address = 0;
643 unsigned short port = 0;
644 convert_sockaddr(saddress, address, port);
645 return port;
646 }
647
648 unsigned long remote_address(void) const
649 {
650 return m_remote_address;
651 }
652
653 unsigned short remote_port(void) const
654 {
655 return m_remote_port;
656 }
657
658 ////////////////////////////////////////////////////////////////////////////
659 // error handling
660
661 void set_error (int error, const char* message = 0) const
662 {
663 if (error != 0)
664 {
665 m_error = error;
666 if (message && (message[0] != 0))
667 m_message = message;
668 else
669 m_message = error_string(error);
670 }
671 }
672
673 int error(void) const
674 {
675 return m_error;
676 }
677
678 void clear_error (void) const
679 {
680 m_error = 0;
681 m_message.erase();
682 }
683
684 std::string message(void) const
685 {
686 return m_message;
687 }
688
689 };
690
691 ////////////////////////////////////////////////////////////////////////////////
692 // Socket - common code to manipulate a socket
693
694 // create an uninitialised socket
695 IP_socket::IP_socket(void) : m_impl(new IP_socket_internals)
696 {
697 }
698
699 // create an initialised socket
700 // - type: create either a TCP or UDP socket - if neither, creates an uninitialised socket
701 IP_socket::IP_socket(IP_socket_type type) : m_impl(new IP_socket_internals)
702 {
703 initialise(type);
704 }
705
706 // destroy the socket, closing it if open
707 IP_socket::~IP_socket(void)
708 {
709 if (m_impl->decrement())
710 delete m_impl;
711 }
712
713 ////////////////////////////////////////////////////////////////////////////
714 // copying is implemented as aliasing
715
716 IP_socket::IP_socket(const IP_socket& right) : m_impl(0)
717 {
718 // make this an alias of right
719 m_impl = right.m_impl;
720 m_impl->increment();
721 }
722
723 IP_socket& IP_socket::operator=(const IP_socket& right)
724 {
725 // make self-copy safe
726 if (m_impl == right.m_impl) return *this;
727 // first dealias the existing implementation
728 if (m_impl->decrement())
729 delete m_impl;
730 // now make this an alias of right
731 m_impl = right.m_impl;
732 m_impl->increment();
733 return *this;
734 }
735
736 ////////////////////////////////////////////////////////////////////////////
737 // initialisation, connection
738
739 // initialise the socket
740 // - type: create either a TCP or UDP socket
741 // - returns success status
742 bool IP_socket::initialise(IP_socket_type type)
743 {
744 return m_impl->initialise(type);
745 }
746
747 // test whether this is an initialised socket
748 // - returns whether this is initialised
749 bool IP_socket::initialised(void) const
750 {
751 return m_impl->initialised();
752 }
753
754 // close, i.e. disconnect the socket
755 // - returns a success flag
756 bool IP_socket::close(void)
757 {
758 return m_impl->close();
759 }
760
761 // function for performing IP lookup (i.e. gethostbyname)
762 // could be standalone but making it a member means that it can use the socket's error handler
763 // - remote_address: IP name (stlplus.sourceforge.net) or dotted number (216.34.181.96)
764 // - returns the IP address as a long integer - zero if there's an error
765 unsigned long IP_socket::ip_lookup(const std::string& remote_address)
766 {
767 return m_impl->ip_lookup(remote_address);
768 }
769
770 // test whether a socket is ready to communicate
771 // - readable: test whether socket is ready to read
772 // - writeable: test whether a socket is ready to write
773 // - timeout: if socket is not ready, time to wait before giving up - in micro-seconds - 0 means don't wait
774 // returns false if not ready or error - use error() method to tell - true if ready
775 bool IP_socket::select(bool readable, bool writeable, unsigned timeout)
776 {
777 return m_impl->select(readable, writeable, timeout);
778 }
779
780 // bind the socket to a port so that it can receive from specific address - typically used by a client
781 // - remote_address: IP number of remote server to send/receive to/from
782 // - local_port: port on local machine to bind to the address
783 // - returns success flag
784 bool IP_socket::bind(unsigned long remote_address, unsigned short local_port)
785 {
786 return m_impl->bind(remote_address, local_port);
787 }
788
789 // bind the socket to a port so that it can receive from any address - typically used by a server
790 // - local_port: port on local machine to bind to the address
791 // - returns success flag
792 bool IP_socket::bind_any(unsigned short local_port)
793 {
794 return m_impl->bind_any(local_port);
795 }
796
797 // initialise a socket and set this socket up to be a listening port
798 // - queue: length of backlog queue to manage - may be zero
799 // - returns success status
800 bool IP_socket::listen(unsigned short queue)
801 {
802 return m_impl->listen(queue);
803 }
804
805 // test for a connection on the object's socket - only applicable if it has been set up as a listening port
806 // - returns true if a connection is ready to be accepted
807 bool IP_socket::accept_ready(unsigned timeout) const
808 {
809 return m_impl->accept_ready(timeout);
810 }
811
812 // accept a connection on the object's socket - only applicable if it has been set up as a listening port
813 // - returns the connection as a new socket
814 IP_socket IP_socket::accept(void)
815 {
816 return m_impl->accept();
817 }
818
819 // client connect to a server
820 // - address: IP number already lookup up with ip_lookup
821 // - port: port to connect to
822 // - returns a success flag
823 bool IP_socket::connect(unsigned long address, unsigned short port)
824 {
825 return m_impl->connect(address, port);
826 }
827
828 // test whether a socket is connected and ready to communicate, returns on successful connect or timeout
829 // - timeout: how long to wait in microseconds if not connected yet
830 // - returns success flag
831 bool IP_socket::connected(unsigned timeout)
832 {
833 return m_impl->connected(timeout);
834 }
835
836 ////////////////////////////////////////////////////////////////////////////
837 // sending/receiving
838
839 // test whether a socket is connected and ready to send data, returns if ready or on timeout
840 // - timeout: how long to wait in microseconds if not connected yet (blocking)
841 // - returns status
842 bool IP_socket::send_ready(unsigned timeout)
843 {
844 return m_impl->send_ready(timeout);
845 }
846
847 // send data through the socket - if the data is long only part of it may
848 // be sent. The sent part is removed from the data, so the same string can
849 // be sent again and again until it is empty.
850 // - data: string containing data to be sent - any data successfully sent is removed
851 // - returns success flag
852 bool IP_socket::send (std::string& data)
853 {
854 return m_impl->send(data);
855 }
856
857 // send data through a connectionless (UDP) socket
858 // the data will be sent as a single packet
859 // - packet: string containing data to be sent - any data successfully sent is removed
860 // - remote_address: address of the remote host to send to - optional if the socket has been connected to remote
861 // - remote_port: port of the remote host to send to - optional if the socket has been connected to remote
862 // - returns success flag
863 bool IP_socket::send_packet(std::string& packet, unsigned long remote_address, unsigned short remote_port)
864 {
865 return m_impl->send_packet(packet, remote_address, remote_port);
866 }
867
868 // send data through a connectionless (UDP) socket
869 // the data will be sent as a single packet
870 // only works if the socket has been connected to remote
871 // - packet: string containing data to be sent - any data successfully sent is removed
872 // - returns success flag
873 bool IP_socket::send_packet(std::string& packet)
874 {
875 return m_impl->send_packet(packet);
876 }
877
878 // test whether a socket is connected and ready to receive data, returns if ready or on timeout
879 // - timeout: how long to wait in microseconds if not connected yet (blocking)
880 // - returns status
881 bool IP_socket::receive_ready(unsigned timeout)
882 {
883 return m_impl->receive_ready(timeout);
884 }
885
886 // receive data through a connection-based (TCP) socket
887 // if the data is long only part of it may be received. The received data
888 // is appended to the string, building it up in stages, so the same string
889 // can be received again and again until all information has been
890 // received.
891 // - data: string receiving data from socket - any data successfully received is appended
892 // - returns success flag
893 bool IP_socket::receive (std::string& data)
894 {
895 return m_impl->receive(data);
896 }
897
898 // receive data through a connectionless (UDP) socket
899 // - packet: string receiving data from socket - any data successfully received is appended
900 // - remote_address: returns the address of the remote host received from
901 // - remote_port: returns the port of the remote host received from
902 // - returns success flag
903 bool IP_socket::receive_packet(std::string& packet, unsigned long& remote_address, unsigned short& remote_port)
904 {
905 return m_impl->receive_packet(packet, remote_address, remote_port);
906 }
907
908 // variant of above which does not give back the address and port of the sender
909 // receive data through a connectionless (UDP) socket
910 // - packet: string receiving data from socket - any data successfully received is appended
911 // - returns success flag
912 bool IP_socket::receive_packet(std::string& packet)
913 {
914 return m_impl->receive_packet(packet);
915 }
916
917 ////////////////////////////////////////////////////////////////////////////
918 // informational
919
920 IP_socket_type IP_socket::type(void) const
921 {
922 return m_impl->type();
923 }
924
925 unsigned short IP_socket::local_port(void) const
926 {
927 return m_impl->local_port();
928 }
929
930 unsigned long IP_socket::remote_address(void) const
931 {
932 return m_impl->remote_address();
933 }
934
935 unsigned short IP_socket::remote_port(void) const
936 {
937 return m_impl->remote_port();
938 }
939
940 ////////////////////////////////////////////////////////////////////////////
941 // error handling
942
943 void IP_socket::set_error (int error, const std::string& message) const
944 {
945 m_impl->set_error(error, message.c_str());
946 }
947
948 void IP_socket::clear_error (void) const
949 {
950 m_impl->clear_error();
951 }
952
953 int IP_socket::error(void) const
954 {
955 return m_impl->error();
956 }
957
958 std::string IP_socket::message(void) const
959 {
960 return m_impl->message();
961 }
962
963 ////////////////////////////////////////////////////////////////////////////////
964
965 } // end namespace stlplus
This page took 0.070585 seconds and 4 git commands to generate.