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