dodo  0.0.1
A C++ library to create containerized Linux services
socket.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the dodo library (https://github.com/jmspit/dodo).
3  * Copyright (c) 2019 Jan-Marten Spit.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, version 3.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 /**
19  * @file socket.cpp
20  * Implements the dodo::network::Socket class.
21  */
22 
23 #include <cstring>
24 #include <iostream>
25 #include <sys/socket.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 
29 #include "network/socket.hpp"
30 #include "common/exception.hpp"
31 
32 namespace dodo::network {
33 
34  Socket Socket::SocketInvalid = Socket();
35 
36  common::SystemError Socket::send( const void* buf, ssize_t len, bool more ) {
37  int flags = MSG_NOSIGNAL;
38  if ( more ) flags = flags | MSG_MORE;
39  ssize_t left = len;
40  ssize_t rc = 0;
41  const char* cp = (const char*)buf;
42  while ( left > 0 ) {
43  rc = ::send( socket_, cp, left, flags );
44  if ( rc < 0 ) break;
45  cp += rc;
46  left -= rc;
47  }
48  if ( rc < 0 ) {
49  switch ( errno ) {
52  return errno;
53  default: throw_SystemExceptionObject( "Socket::send failed", errno, this );
54  };
55  } else if ( left ) throw_SystemExceptionObject( "Socket::send not all bytes send", errno, this );
56  else return common::SystemError::ecOK;
57  }
58 
59  common::SystemError Socket::sendTo( const Address& address, const void* buf, ssize_t len ) {
60  int flags = 0;
61  ssize_t left = len;
62  ssize_t rc = 0;
63  const char* cp = (const char*)buf;
64  while ( left > 0 ) {
65  rc = ::sendto( socket_, cp, left, flags, (const sockaddr*)&(address.addr_), sizeof(address.addr_) );
66  if ( rc < 0 ) break;
67  cp += rc;
68  left -= rc;
69  }
70  if ( rc < 0 ) {
71  switch ( errno ) {
74  return errno;
75  default: throw_SystemExceptionObject( "Socket::send failed", errno, this );
76  };
77  } else if ( left ) throw_SystemExceptionObject( "Socket::send not all bytes send", errno, this );
78  else return common::SystemError::ecOK;
79  }
80 
81  common::SystemError Socket::receive( void* buf, ssize_t request, ssize_t &received ) {
82  received = 0;
83  ssize_t rc = ::recv( socket_, buf, request, 0 );
84  if ( rc < 0 ) {
85  switch ( errno ) {
89  return errno;
90  default: throw_SystemExceptionObject( "Socket::receive failed", errno, this );
91  };
92  } else {
93  received = rc;
95  }
96  }
97 
99  Socket* ret = new Socket();
100  *ret = Socket::SocketInvalid;
101  int rc = ::accept( socket_, nullptr, nullptr );
102  if ( rc == -1 ) {
103  if ( errno != EAGAIN && errno != EWOULDBLOCK )
104  throw_SystemExceptionObject( "Socket::accept failed", errno, this );
105  else
106  *ret = rc;
107  } else *ret = rc;
108  return ret;
109  }
110 
111 }
dodo::network::Socket::Socket
Socket()
Default constructor creates an invalid socket.
Definition: socket.hpp:57
dodo::common::SystemError::ecENOTCONN
@ ecENOTCONN
107 Transport endpoint is not connected
Definition: systemerror.hpp:167
dodo::common::SystemError::ecECONNREFUSED
@ ecECONNREFUSED
111 Connection refused
Definition: systemerror.hpp:171
dodo::network::Address
Generic network Address, supporting ipv4 and ipv6 transparently.
Definition: address.hpp:90
dodo::common::SystemError::ecEAGAIN
@ ecEAGAIN
11 Try again
Definition: systemerror.hpp:71
dodo::network::Socket::receive
virtual common::SystemError receive(void *buf, ssize_t request, ssize_t &received)
Receive bytes.
Definition: socket.cpp:81
dodo::network::Socket::SocketInvalid
static Socket SocketInvalid
An invalid SocketInvalid for comparison convenience - initialized to a Socket with socket fd=-1.
Definition: socket.hpp:129
dodo::network::Socket::sendTo
virtual common::SystemError sendTo(const Address &address, const void *buf, ssize_t len)
Send raw packets to the given Address.
Definition: socket.cpp:59
dodo::network::BaseSocket::socket_
int socket_
The socket file decsriptor.
Definition: basesocket.hpp:503
socket.hpp
throw_SystemExceptionObject
#define throw_SystemExceptionObject(what, errno, thing)
Throws an Exception with errno, passes FILE and LINE to constructor.
Definition: exception.hpp:196
dodo::common::SystemError::ecOK
@ ecOK
0 Not an error, success
Definition: systemerror.hpp:60
dodo::network
Interface for network communication.
Definition: address.hpp:37
dodo::network::Socket
A Linux socket.
Definition: socket.hpp:50
dodo::network::Socket::accept
virtual Socket * accept()
Accepts a connection request and return a pointer to a new Socket for the new connection,...
Definition: socket.cpp:98
exception.hpp
dodo::common::SystemError
Linux system error primitive to provide a consistent interface to Linux error codes.
Definition: systemerror.hpp:53
dodo::network::Address::addr_
struct sockaddr_storage addr_
The address storage (for either ipv4 or ipv6).
Definition: address.hpp:289
dodo::common::SystemError::ecECONNRESET
@ ecECONNRESET
104 Connection reset by peer
Definition: systemerror.hpp:164
dodo::network::Socket::send
virtual common::SystemError send(const void *buf, ssize_t len, bool more=false)
Send len bytes as a bytestream.
Definition: socket.cpp:36