24 #include <netcomm/socket/socket.h> 26 #include <core/exceptions/system.h> 27 #include <utils/time/time.h> 34 #include <sys/types.h> 35 #include <sys/socket.h> 42 #include <netinet/in.h> 43 #include <netinet/in_systm.h> 44 #include <netinet/ip.h> 57 # include <sys/ioctl.h> 131 const short Socket::POLL_RDHUP = 0;
157 this->timeout = timeout;
158 if ( (sock_fd = socket(domain, type, protocol)) == -1 ) {
164 if ( fcntl(sock_fd, F_SETFL, O_NONBLOCK) == -1 ) {
196 memcpy(client_addr, socket.
client_addr, client_addr_len);
210 if ( client_addr != NULL ) {
221 if ( sock_fd != -1 ) {
239 if ( sock_fd == -1 )
throw SocketException(
"Trying to connect invalid socket");
241 if (timeout == 0.f) {
242 if ( ::connect(sock_fd, addr_port, struct_size) < 0 ) {
246 struct timeval start, now;
247 gettimeofday(&start, NULL);
249 if ( ::connect(sock_fd, addr_port, struct_size) < 0 ) {
250 if ( (errno != EINPROGRESS) &&
251 (errno != EALREADY) ) {
255 gettimeofday(&now, NULL);
272 if ( sock_fd == -1 )
throw SocketException(
"Trying to connect invalid socket");
275 struct ::sockaddr_in host;
278 h = gethostbyname(hostname);
283 memset(&host, 0,
sizeof(host));
284 host.sin_family = AF_INET;
285 memcpy((
char *)&host.sin_addr.s_addr, h->h_addr, h->h_length);
286 host.sin_port = htons(port);
288 connect((
struct sockaddr *)&host,
sizeof(host));
300 struct ::sockaddr_in host;
302 host.sin_family = AF_INET;
303 host.sin_addr.s_addr = INADDR_ANY;
304 host.sin_port = htons(port);
307 if ( setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &reuse,
sizeof(reuse)) == -1) {
311 if (::bind(sock_fd, (
struct sockaddr *) &host,
sizeof(host)) < 0) {
326 struct ::sockaddr_in host;
328 h = gethostbyname(hostname);
333 memset(&host, 0,
sizeof(host));
334 host.sin_family = AF_INET;
335 memcpy(&host.sin_addr.s_addr, h->h_addr, h->h_length);
336 host.sin_port = htons(port);
338 host.sin_family = AF_INET;
339 host.sin_addr.s_addr = INADDR_ANY;
340 host.sin_port = htons(port);
342 if (::bind(sock_fd, (
struct sockaddr *) &host,
sizeof(host)) < 0) {
359 if ( ::listen(sock_fd, backlog) ) {
373 struct ::sockaddr_in tmp_client_addr;
374 unsigned int tmp_client_addr_len =
sizeof(struct ::sockaddr_in);
378 a_sock_fd = ::accept(sock_fd, (sockaddr *)&tmp_client_addr, &tmp_client_addr_len);
379 if ( a_sock_fd == -1 ) {
380 if (errno != EWOULDBLOCK) {
397 struct ::sockaddr_in *tmp_client_addr_alloc = (struct ::sockaddr_in *)malloc(
sizeof(struct ::sockaddr_in));
398 memcpy(tmp_client_addr_alloc, &tmp_client_addr,
sizeof(struct ::sockaddr_in));
413 if (sock_fd == -1)
return false;
420 FD_SET(sock_fd, &rfds);
424 retval = select(sock_fd + 1, &rfds, NULL, NULL, &tv);
426 perror(
"select() failed");
454 if ( sock_fd == -1 ) {
462 if ( ::poll(&pfd, 1, timeout) == -1 ) {
463 if ( errno == EINTR ) {
484 unsigned int bytes_written = 0;
485 struct timeval start, now;
487 gettimeofday(&start, NULL);
490 retval = ::write(sock_fd, (
char *)buf + bytes_written, count - bytes_written);
492 if (errno != EAGAIN) {
499 bytes_written += retval;
501 gettimeofday(&start, NULL);
503 gettimeofday(&now, NULL);
505 }
while ((bytes_written < count) && (
time_diff_sec(now, start) < timeout) );
507 if ( bytes_written < count) {
528 unsigned int bytes_read = 0;
531 struct timeval start, now;
533 gettimeofday(&start, NULL);
537 retval = ::read(sock_fd, (
char *)buf + bytes_read, count - bytes_read);
539 if (errno != EAGAIN) {
546 bytes_read += retval;
548 gettimeofday(&start, NULL);
550 gettimeofday(&now, NULL);
552 }
while ((bytes_read < count) && (
time_diff_sec(now, start) < timeout) );
555 retval = ::read(sock_fd, (
char *)buf, count);
556 if ( (retval == -1) && (errno != EAGAIN) ) {
562 }
while (retval < 0);
567 retval = ::read(sock_fd, (
char *)buf + bytes_read, count - bytes_read);
570 }
else if (retval == 0) {
573 bytes_read += retval;
576 }
while (bytes_read < count);
579 retval = ::read(sock_fd, (
char *)buf, count);
580 if ( (retval == -1) && (errno != EAGAIN) ) {
586 }
while (retval < 0);
590 if ( read_all && (bytes_read < count)) {
631 if ( (rv = ::recv(sock_fd, buf, buf_len, 0)) == -1 ) {
633 }
else if ( rv == 0 ) {
648 const struct sockaddr *addr, socklen_t addr_len)
651 unsigned int bytes_written = 0;
652 struct timeval start, now;
654 gettimeofday(&start, NULL);
657 retval = ::sendto(sock_fd, (
char *)buf + bytes_written, buf_len - bytes_written, 0,
660 if (errno != EAGAIN) {
667 bytes_written += retval;
669 gettimeofday(&start, NULL);
671 gettimeofday(&now, NULL);
673 }
while ((bytes_written < buf_len) && (
time_diff_sec(now, start) < timeout) );
675 if ( bytes_written < buf_len) {
694 struct sockaddr *addr, socklen_t *addr_len)
698 if ( (rv = ::recvfrom(sock_fd, buf, buf_len, 0, addr, addr_len)) == -1) {
700 }
else if ( rv == 0 ) {
714 if ( sock_fd == -1 )
return false;
717 unsigned int len =
sizeof(i);
718 if ( getsockopt(sock_fd, SOL_SOCKET, SO_ACCEPTCONN, &i, &len) == -1 ) {
719 throw SocketException(
"Socket::listening(): getsockopt failed", errno);
734 if ( sock_fd == -1 )
throw SocketException(
"Cannot get MTU of disconnected socket");
737 unsigned int len =
sizeof(m);
738 if ( getsockopt(sock_fd, IPPROTO_IP, IP_MTU, &m, &len) == -1 ) {
745 #elif defined __FreeBSD__ 747 if (ioctl(sock_fd, SIOCGIFMTU, &ifr) != -1)
virtual void connect(const char *hostname, const unsigned short int port)
Connect socket.
static const short POLL_ERR
Error condition.
virtual void close()
Close socket.
virtual void write(const void *buf, size_t count)
Write to the socket.
static const short POLL_PRI
There is urgent data to read (e.g., out-of-band data on TCP socket; pseudo-terminal master in packet ...
Fawkes library namespace.
SocketException(const char *msg, int _errno)
Constructor.
virtual size_t recv(void *buf, size_t buf_len)
Read from socket.
static const short POLL_IN
Data can be read.
struct::sockaddr_in * client_addr
Client address, set if connected.
int _errno
Error number, should be used if the error was caused by a method that supplies errno.
unsigned int client_addr_len
length in bytes of client address.
virtual bool available()
Check if data is available.
virtual Socket * accept()
Accept connection.
virtual const char * what() const
Get primary string.
Base class for exceptions in Fawkes.
double time_diff_sec(const timeval &a, const timeval &b)
Calculate time difference of two time structs.
virtual size_t read(void *buf, size_t count, bool read_all=true)
Read from socket.
The current system call has been interrupted (for instance by a signal).
virtual void bind(const unsigned short int port)
Bind socket.
static const short POLL_RDHUP
Stream socket peer closed connection, or shut down writing half of connection.
virtual ~Socket()
Destructor.
virtual bool listening()
Is socket listening for connections?
virtual unsigned int mtu()
Maximum Transfer Unit (MTU) of socket.
virtual short poll(int timeout=-1, short what=POLL_IN|POLL_HUP|POLL_PRI|POLL_RDHUP)
Wait for some event on socket.
int sock_fd
Socket file descriptor.
virtual void send(void *buf, size_t buf_len)
Write to the socket.
static const short POLL_HUP
Hang up.
static const short POLL_NVAL
Invalid request.
virtual void listen(int backlog=1)
Listen on socket.
float timeout
Timeout in seconds for various operations.
static const short POLL_OUT
Writing will not block.