├── .gitignore ├── .travis.yml ├── C++ ├── CMakeLists.txt ├── dgramclient.cpp ├── dgramoverstream.cpp ├── exception.cpp ├── framing.cpp ├── inetbase.cpp ├── inetclientdgram.cpp ├── inetclientstream.cpp ├── inetdgram.cpp ├── inetserverdgram.cpp ├── inetserverstream.cpp ├── select.cpp ├── socket.cpp ├── streamclient.cpp ├── unixbase.cpp ├── unixclientdgram.cpp ├── unixclientstream.cpp ├── unixdgram.cpp ├── unixserverdgram.cpp └── unixserverstream.cpp ├── C ├── CMakeLists.txt ├── inet │ └── libinetsocket.c └── unix │ └── libunixsocket.c ├── CMakeLists.txt ├── CONTRIBUTORS ├── LICENSE ├── README.md ├── doc ├── libsocket++ │ ├── DOCUMENTATION++.html │ ├── DOCUMENTATION++.mkd │ ├── classes.dia │ └── classes.svg └── libsocket │ ├── DOCUMENTATION.html │ └── DOCUMENTATION.mkd ├── doxyconf.conf ├── doxymain.dox ├── examples++ ├── README.md ├── build.sh ├── dgram_over_stream.cpp ├── echo │ ├── build.sh │ ├── echo_client_conn.cpp │ ├── echo_client_sndto.cpp │ └── echo_server.cpp ├── framing.cpp ├── http_examples │ ├── build.sh │ ├── http.cpp │ ├── http_2.cpp │ └── http_epoll.cpp ├── simple_tcp │ ├── build.sh │ ├── client.cpp │ └── server.cpp ├── unix_dgram │ ├── build.sh │ ├── unix_dgram_client.cpp │ └── unix_dgram_server.cpp ├── unix_dgram_syslogclient.cpp └── unix_stream │ ├── build.sh │ ├── unix_client_stream.cpp │ └── unix_server_stream.cpp ├── examples ├── build.sh ├── echo │ ├── build.sh │ ├── echo_dgram_client.c │ ├── echo_dgram_connect_client.c │ └── echo_dgram_server.c ├── get_address_family.c ├── http.c ├── multicast_listen.c ├── transmission │ ├── build.sh │ ├── transmission_client.c │ └── transmission_server.c ├── unix_dgram │ ├── build.sh │ ├── unix_dgram_client.c │ ├── unix_dgram_connect_client.c │ └── unix_dgram_server.c └── unix_stream │ ├── build.sh │ ├── unix_stream_client.c │ └── unix_stream_server.c ├── headers ├── CMakeLists.txt ├── conf.h.in ├── dgramclient.hpp ├── dgramoverstream.hpp ├── doxymeta.dox ├── epoll.hpp ├── exception.hpp ├── framing.hpp ├── inetbase.hpp ├── inetclientdgram.hpp ├── inetclientstream.hpp ├── inetdgram.hpp ├── inetserverdgram.hpp ├── inetserverstream.hpp ├── libinetsocket.h ├── libunixsocket.h ├── select.hpp ├── socket.hpp ├── streamclient.hpp ├── unixbase.hpp ├── unixclientdgram.hpp ├── unixclientstream.hpp ├── unixdgram.hpp ├── unixserverdgram.hpp └── unixserverstream.hpp ├── libsocketConfig.cmake.in ├── libsocketConfigVersion.cmake.in └── package.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | a.out 3 | *.so* 4 | cl 5 | srv 6 | *.swp 7 | *.a 8 | *.kdev4 9 | headers/conf.h 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | compiler: 3 | - clang 4 | before_install: 5 | - sudo apt-get update 6 | - sudo apt-get install lib32stdc++6 wget ca-certificates -qq 7 | # I know and I don't care. 8 | - wget --no-check-certificate https://cmake.org/files/v3.12/cmake-3.12.4-Linux-x86_64.sh 9 | - chmod a+x cmake-3.12.4-Linux-x86_64.sh 10 | - sudo ./cmake-3.12.4-Linux-x86_64.sh --skip-license --prefix=/usr 11 | script: 12 | - cmake -DCMAKE_CXX_COMPILER=clang++ 13 | - make 14 | - sudo make install 15 | -------------------------------------------------------------------------------- /C++/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") # -DVERBOSE") 4 | 5 | ADD_DEFINITIONS("-DMIXED") 6 | 7 | SET(sources 8 | dgramclient.cpp 9 | dgramoverstream.cpp 10 | framing.cpp 11 | inetbase.cpp 12 | inetclientstream.cpp 13 | inetserverdgram.cpp 14 | select.cpp 15 | streamclient.cpp 16 | unixclientdgram.cpp 17 | unixdgram.cpp 18 | unixserverstream.cpp 19 | exception.cpp 20 | inetclientdgram.cpp 21 | inetdgram.cpp 22 | inetserverstream.cpp 23 | socket.cpp 24 | unixbase.cpp 25 | unixclientstream.cpp 26 | unixserverdgram.cpp 27 | ) 28 | 29 | ADD_DEFINITIONS(-fPIC) # for the static library which needs to be linked into the shared libsocket++.so object. 30 | ADD_LIBRARY(socket++_o OBJECT ${sources}) 31 | 32 | IF(BUILD_SHARED_LIBS) 33 | ADD_LIBRARY(socket++ SHARED $) 34 | 35 | TARGET_LINK_LIBRARIES(socket++ socket_int) 36 | 37 | INSTALL(TARGETS socket++ DESTINATION ${LIB_DIR}) 38 | ENDIF() 39 | 40 | IF(BUILD_STATIC_LIBS) 41 | ADD_LIBRARY(socket++_int STATIC $) 42 | 43 | SET_TARGET_PROPERTIES(socket++_int PROPERTIES OUTPUT_NAME socket++) 44 | 45 | TARGET_LINK_LIBRARIES(socket++_int socket_int) 46 | 47 | INSTALL(TARGETS socket++_int DESTINATION ${LIB_DIR}) 48 | ENDIF() 49 | -------------------------------------------------------------------------------- /C++/dgramclient.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 6 | The committers of the libsocket project, all rights reserved 7 | (c) 2012, dermesser 8 | 9 | Redistribution and use in source and binary forms, with or without 10 | modification, are permitted provided that the following conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright notice, 13 | this list of conditions and the following disclaimer. 14 | 2. Redistributions in binary form must reproduce the above copyright notice, 15 | this list of conditions and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 19 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 22 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | */ 30 | 31 | /** 32 | * @file dgramclient.cpp 33 | * @brief Base class for all datagram-based socket classes 34 | * 35 | * dgramclient.cpp contains the class dgram_client_socket. This 36 | * class provides the read/write functions for connected datagram 37 | * sockets (alias client dgram sockets...). This helps to avoid 38 | * writing the same code more than one time. 39 | * The client datagram classes for specific domains which are 40 | * unix_dgram_client and inet_dgram_client inherit the functions 41 | * declared here to get the ability to send and receive 42 | * data via connected datagram sockets. It is not possible to use 43 | * a class which has this functions also for stream sockets because 44 | * the functions have to check if the socket is connected (bool connected). 45 | * In the stream classes, this check is realized by checking if the file 46 | * descriptor is -1 or not. 47 | * @addtogroup libsocketplusplus 48 | * @{ 49 | */ 50 | 51 | #include 52 | #include 53 | 54 | namespace libsocket { 55 | using std::string; 56 | 57 | dgram_client_socket::dgram_client_socket(void) : connected(false) {} 58 | 59 | /** 60 | * @brief Receive data from a connected DGRAM socket 61 | * 62 | * If a datagram socket is connected, this function may be called to receive 63 | * data sent from the host connected to. 64 | * 65 | * @param buf Area to write the data to 66 | * @param len How many data we want to receive 67 | * @param flags Flags to be passed to `recv(2)` 68 | * 69 | * @retval >0 n bytes were received. 70 | * @retval 0 0 bytes were received. (EOF?) 71 | * @retval -1 Something went wrong. 72 | */ 73 | ssize_t dgram_client_socket::rcv(void* buf, size_t len, int flags) { 74 | ssize_t bytes; 75 | 76 | memset(buf, 0, len); 77 | 78 | if (-1 == (bytes = recv(sfd, buf, len, flags))) 79 | throw socket_exception(__FILE__, __LINE__, 80 | "dgram_client_socket::rcv() - recv() failed!"); 81 | 82 | return bytes; 83 | } 84 | 85 | /** 86 | * @brief Receive data from connected datagram socket 87 | * 88 | * If a datagram socket is connected, you may receive data from it using 89 | * stream-like functions. 90 | * 91 | * @param sock The socket to receive data from 92 | * @param dest The string to write data to. This string has to be resized to the 93 | * number of bytes you wish to receive. 94 | */ 95 | dgram_client_socket& operator>>(dgram_client_socket& sock, string& dest) { 96 | ssize_t read_bytes; 97 | 98 | char* buffer = new char[dest.size()]; 99 | 100 | memset(buffer, 0, dest.size()); 101 | 102 | if (-1 == (read_bytes = read(sock.sfd, buffer, dest.size()))) { 103 | delete[] buffer; 104 | if (sock.is_nonblocking && errno == EWOULDBLOCK) { 105 | dest.clear(); 106 | return sock; 107 | } else 108 | throw socket_exception(__FILE__, __LINE__, 109 | ">>(dgram_client_socket, std::string) " 110 | "input: Error while reading!"); 111 | } 112 | 113 | if (read_bytes < static_cast(dest.size())) 114 | dest.resize(read_bytes); // So the client doesn't print content more 115 | // than one time 116 | // and it can check if the string's length is 0 (end of transmission) 117 | 118 | dest.assign(buffer, read_bytes); 119 | 120 | delete[] buffer; 121 | 122 | return sock; 123 | } 124 | 125 | /** 126 | * @brief Send data to connected socket 127 | * 128 | * @param buf Pointer to the data 129 | * @param len The length of the buffer 130 | * @param flags Flags for `send(2)` 131 | * 132 | * @retval n *n* bytes were sent 133 | * @retval <0 An error occurred. 134 | */ 135 | ssize_t dgram_client_socket::snd(const void* buf, size_t len, int flags) { 136 | ssize_t bytes; 137 | 138 | if (connected != true) 139 | throw socket_exception( 140 | __FILE__, __LINE__, 141 | "dgram_client_socket::snd() - Socket is not connected!", false); 142 | 143 | if (-1 == (bytes = send(sfd, buf, len, flags))) 144 | throw socket_exception(__FILE__, __LINE__, 145 | "dgram_client_socket::snd() - send() failed!"); 146 | 147 | return bytes; 148 | } 149 | 150 | /** 151 | * @brief Send data to connected peer 152 | * 153 | * Usage: `socket << "Abcde";` 154 | */ 155 | dgram_client_socket& operator<<(dgram_client_socket& sock, const char* str) { 156 | if (str == NULL) 157 | throw socket_exception( 158 | __FILE__, __LINE__, 159 | "dgram_client_socket <<(const char*) output: Null buffer given!"); 160 | if (sock.connected == false) 161 | throw socket_exception(__FILE__, __LINE__, 162 | "dgram_client_socket <<(const char*) output: " 163 | "DGRAM socket not connected!"); 164 | 165 | size_t len = strlen(str); 166 | 167 | if (-1 == write(sock.sfd, str, len)) 168 | throw socket_exception( 169 | __FILE__, __LINE__, 170 | "dgram_client_socket <<(const char*) output: Write failed!"); 171 | 172 | return sock; 173 | } 174 | 175 | /** 176 | * @brief Send data to connected peer 177 | * 178 | * Usage: `socket << "Abcde";` 179 | */ 180 | dgram_client_socket& operator<<(dgram_client_socket& sock, const string& str) { 181 | if (sock.connected == false) 182 | throw socket_exception(__FILE__, __LINE__, 183 | "dgram_client_socket <<(std::string) output: " 184 | "DGRAM socket not connected!"); 185 | if (-1 == write(sock.sfd, str.c_str(), str.size())) 186 | throw socket_exception( 187 | __FILE__, __LINE__, 188 | "dgram_client_socket <<(std::string) output: Write failed!"); 189 | 190 | return sock; 191 | } 192 | 193 | /** 194 | * @deprecated (use is_connected()) 195 | * 196 | * Look up if socket is connected. 197 | */ 198 | bool dgram_client_socket::getconn(void) const { return is_connected(); } 199 | 200 | /** 201 | * Returns true if the socket is in a connected state. 202 | */ 203 | bool dgram_client_socket::is_connected(void) const { return connected; } 204 | } // namespace libsocket 205 | 206 | /** 207 | * @} 208 | */ 209 | -------------------------------------------------------------------------------- /C++/dgramoverstream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 6 | The committers of the libsocket project, all rights reserved 7 | (c) 2016, dermesser 8 | 9 | Redistribution and use in source and binary forms, with or without 10 | modification, are permitted provided that the following conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright notice, 13 | this list of conditions and the following disclaimer. 14 | 2. Redistributions in binary form must reproduce the above copyright notice, 15 | this list of conditions and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 19 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 22 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | */ 30 | 31 | /** 32 | * @file dgramoverstream.cpp 33 | * @brief Simple framing over streams. 34 | * @addtogroup libsocketplusplus 35 | * @{ 36 | */ 37 | 38 | #include 39 | #include 40 | 41 | namespace libsocket { 42 | 43 | dgram_over_stream::dgram_over_stream(stream_client_socket socket) 44 | : inner(std::unique_ptr( 45 | new stream_client_socket(std::move(socket)))) { 46 | enable_nagle(false); 47 | } 48 | 49 | dgram_over_stream::dgram_over_stream( 50 | std::unique_ptr inner_) 51 | : inner(std::move(inner_)) { 52 | enable_nagle(false); 53 | } 54 | 55 | /** 56 | * @brief Set TCP_NODELAY to `!enabled` on the underlying socket. 57 | * 58 | * TCP_NODELAY causes writes to the socket to be pushed to the network 59 | * immediately. This emulates the behavior of datagram sockets, and is very 60 | * useful for datagram-like use of streams, like this class implements. However, 61 | * it creates slight overhead as data are not batched. 62 | * 63 | * (clarification: If Nagle's algorithm is *enabled*, that means that 64 | * `TCP_NODELAY` is *disabled*, and vice versa) 65 | */ 66 | void dgram_over_stream::enable_nagle(bool enabled) const { 67 | int enabled_ = int(!enabled); 68 | inner->set_sock_opt(IPPROTO_TCP, TCP_NODELAY, (const char*)&enabled_, 69 | sizeof(int)); 70 | } 71 | 72 | ssize_t dgram_over_stream::sndmsg(const std::string& msg) { 73 | return sndmsg(msg.c_str(), msg.size()); 74 | } 75 | 76 | /** 77 | * @brief Receive a message and place it into dst. 78 | * 79 | * No more than dst.size() bytes will be received and placed into dst. 80 | */ 81 | ssize_t dgram_over_stream::rcvmsg(std::string* dst) { 82 | uint32_t expected = receive_header(); 83 | 84 | if (expected <= dst->size()) dst->resize(expected); 85 | 86 | size_t to_receive = dst->size(); 87 | size_t received = 0; 88 | 89 | while (received < to_receive) { 90 | ssize_t result = receive_bytes(to_receive - received); 91 | 92 | if (result < 0) 93 | throw socket_exception( 94 | __FILE__, __LINE__, 95 | "dgram_over_stream::rcvmsg(): Could not receive message!", 96 | false); 97 | 98 | dst->replace(received, result, RECV_BUF); 99 | 100 | received += (size_t)result; 101 | } 102 | 103 | // Consume remaining frame that doesn't fit into dst. 104 | ssize_t rest = expected - to_receive; 105 | while (rest > 0) { 106 | rest -= receive_bytes(rest); 107 | } 108 | 109 | return received; 110 | } 111 | 112 | /** 113 | * @brief Send the message `msg` as one frame. 114 | * @returns How many bytes were sent; should be `msg.size()`. 115 | * @throws socket_exception 116 | */ 117 | ssize_t dgram_over_stream::sndmsg(const std::vector& msg) { 118 | return sndmsg(static_cast(msg.data()), msg.size()); 119 | } 120 | 121 | /** 122 | * @brief Receive up to `dst.size()` bytes and store them in `dst`. 123 | * @returns Number of bytes actually received. 124 | * @throws socket_exception 125 | * 126 | * Resize `dst` before calling in order to adjust the number of bytes you will 127 | * receive. 128 | */ 129 | ssize_t dgram_over_stream::rcvmsg(std::vector* dst) { 130 | uint32_t expected = receive_header(); 131 | 132 | if (expected <= dst->size()) dst->resize(expected); 133 | 134 | size_t to_receive = dst->size(); 135 | size_t received = 0; 136 | std::vector::iterator dst_iter = dst->begin(); 137 | 138 | while (received < to_receive) { 139 | ssize_t result = receive_bytes(to_receive - received); 140 | 141 | if (result < 0) 142 | throw socket_exception( 143 | __FILE__, __LINE__, 144 | "dgram_over_stream::rcvmsg(): Could not receive message!", 145 | false); 146 | 147 | for (ssize_t i = 0; i < result; i++, dst_iter++) 148 | *dst_iter = RECV_BUF[i]; 149 | 150 | received += result; 151 | } 152 | 153 | // Consume remaining frame that doesn't fit into dst. 154 | ssize_t rest = expected - to_receive; 155 | while (rest > 0) { 156 | rest -= receive_bytes(rest); 157 | } 158 | 159 | return received; 160 | } 161 | 162 | /** 163 | * @brief Send the message in buf with length len as one frame. 164 | * @returns The total number of bytes sent. 165 | * @throws A socket_exception. 166 | */ 167 | ssize_t dgram_over_stream::sndmsg(const void* buf, size_t len) { 168 | encode_uint32(uint32_t(len), prefix_buffer); 169 | ssize_t result = inner->snd(prefix_buffer, FRAMING_PREFIX_LENGTH, 0); 170 | 171 | if (result < 0) return result; 172 | 173 | result = inner->snd(buf, len, 0); 174 | 175 | if (result < 0) return result; 176 | 177 | return result; 178 | } 179 | 180 | /** 181 | * @brief Receive a message and store the first `len` bytes into `buf`. 182 | * @returns The number of bytes received. 183 | * @throws A socket_exception. 184 | * 185 | * Bytes in the message beyond `len` are discarded. 186 | */ 187 | ssize_t dgram_over_stream::rcvmsg(void* dst, size_t len) { 188 | uint32_t expected = receive_header(); 189 | 190 | size_t to_receive = len < expected ? len : expected; 191 | size_t received = 0; 192 | 193 | while (received < to_receive) { 194 | ssize_t result = receive_bytes(to_receive - received); 195 | 196 | if (result < 0) 197 | throw socket_exception( 198 | __FILE__, __LINE__, 199 | "dgram_over_stream::rcvmsg(): Could not receive message!", 200 | false); 201 | 202 | memcpy(dst, RECV_BUF, result); 203 | dst = static_cast(static_cast(dst) + result); 204 | received += result; 205 | } 206 | 207 | // Consume remaining frame that doesn't fit into dst. 208 | ssize_t rest = expected - to_receive; 209 | while (rest > 0) { 210 | rest -= receive_bytes(rest); 211 | } 212 | return received; 213 | } 214 | 215 | // Places up to n bytes into this->RECV_BUF. 216 | ssize_t dgram_over_stream::receive_bytes(size_t n) { 217 | if (n == 0) return 0; 218 | 219 | // Ignore rest of message. 220 | ssize_t rest_len = n > RECV_BUF_SIZE ? RECV_BUF_SIZE : n; 221 | size_t pos = 0; 222 | 223 | while (rest_len > 0) { 224 | ssize_t recvd = inner->rcv(RECV_BUF + pos, rest_len, 0); 225 | 226 | if (recvd <= 0) return n - rest_len; 227 | 228 | rest_len -= recvd; 229 | pos += recvd; 230 | } 231 | 232 | return pos; 233 | } 234 | 235 | /** 236 | * @brief Receive and decode length header. 237 | * @returns The expected length received. 238 | * @throws socket_exception 239 | */ 240 | uint32_t dgram_over_stream::receive_header(void) { 241 | ssize_t pos = 0; 242 | 243 | do { 244 | ssize_t result = 245 | inner->rcv(prefix_buffer + pos, FRAMING_PREFIX_LENGTH, 0); 246 | 247 | if (result < 0) 248 | throw socket_exception(__FILE__, __LINE__, 249 | "dgram_over_stream::receive_header(): Could " 250 | "not receive length prefix!", 251 | false); 252 | 253 | pos += result; 254 | } while (pos < 4); 255 | 256 | return decode_uint32(prefix_buffer); 257 | } 258 | } // namespace libsocket 259 | 260 | /** 261 | * @} 262 | */ 263 | -------------------------------------------------------------------------------- /C++/exception.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* 8 | The committers of the libsocket project, all rights reserved 9 | (c) 2012, dermesser 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | 14 | 1. Redistributions of source code must retain the above copyright notice, 15 | this list of conditions and the following disclaimer. 16 | 2. Redistributions in binary form must reproduce the above copyright notice, 17 | this list of conditions and the following disclaimer in the documentation 18 | and/or other materials provided with the distribution. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 21 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 24 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 27 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | /** 34 | * @file exception.cpp 35 | * @brief Exception class in libsocket **CLASS FOR INTERNAL USE ONLY** 36 | * 37 | * The class defined here, socket_exception, is a 38 | * class for exception objects. Objects instantiated 39 | * from this class are thrown if something goes wrong. 40 | * 41 | * The class contains only the data member mesg and the 42 | * constructor which constructs the error string in mesg. 43 | * Typically, you'd create an object of this class with the 44 | * following call: `socket_exception(__FILE__,__LINE__,"Error Message");` 45 | * 46 | * The tokens are substituded by the preprocessor and show where 47 | * the error occurred. 48 | * 49 | * @addtogroup libsocketplusplus 50 | * @{ 51 | */ 52 | 53 | #include 54 | 55 | namespace libsocket { 56 | using std::string; 57 | 58 | /** 59 | * @brief Constructor of a socket_exception object 60 | * 61 | * This constructor creates a new socket_exception object. 62 | * 63 | * @param f File in which the error comes (__FILE__) 64 | * @param l Line (__LINE__) 65 | * @param m Description of the error. 66 | */ 67 | socket_exception::socket_exception(const string& file, int line, 68 | const string& message, bool show_errno) { 69 | std::ostringstream message_stream; 70 | 71 | // Saving errno here should be safe 72 | err = errno; 73 | 74 | message_stream << file << ":" << line << ": " << message; 75 | 76 | if (show_errno) message_stream << " (" << std::strerror(errno) << ")"; 77 | 78 | message_stream << "\n"; 79 | 80 | mesg = message_stream.str(); 81 | } 82 | } // namespace libsocket 83 | 84 | /** 85 | * @} 86 | */ 87 | -------------------------------------------------------------------------------- /C++/framing.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | /* 7 | The committers of the libsocket project, all rights reserved 8 | (c) 2016, dermesser 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | 1. Redistributions of source code must retain the above copyright notice, 14 | this list of conditions and the following disclaimer. 15 | 2. Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | */ 31 | 32 | /** 33 | * @file framing.cpp 34 | * @brief Utility functions for framing. 35 | * 36 | * @addtogroup libsocketplusplus 37 | * @{ 38 | */ 39 | 40 | namespace libsocket { 41 | void encode_uint32(uint32_t n, char* dst) { 42 | for (int i = 3; i >= 0; i--) { 43 | dst[i] = n >> (8 * (3 - i)); 44 | } 45 | } 46 | 47 | uint32_t decode_uint32(const char* src) { 48 | uint32_t result = 0; 49 | // We store unsigned numbers in signed chars; convert, otherwise the MSB 50 | // being set would be interpreted as sign and taken over to uint32_t's MSB. 51 | const unsigned char* src_ = (const unsigned char*)src; 52 | 53 | for (int i = 3; i >= 0; i--) { 54 | result |= uint32_t(src_[i]) << (8 * (3 - i)); 55 | } 56 | 57 | return result; 58 | } 59 | } // namespace libsocket 60 | 61 | /** 62 | * @} 63 | */ 64 | -------------------------------------------------------------------------------- /C++/inetbase.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | /* 4 | The committers of the libsocket project, all rights reserved 5 | (c) 2012, dermesser 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, 11 | this list of conditions and the following disclaimer. 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 17 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | */ 28 | 29 | /** 30 | * @file inetbase.cpp 31 | * @brief The base class for all internet-based sockets. 32 | * 33 | * inetbase.cpp defines the class inet_socket. This class 34 | * is used as base class in the hierarchy between socket and 35 | * the next specific class. Inheriting classes are inet_dgram, 36 | * inet_stream_client and inet_stream_server. 37 | * 38 | * The class contains the data elements host and port. If the inheriting 39 | * class is a client, like inet_stream_client or inet_dgram_client (via 40 | * inet_dgram), this fields contain the remote peer. If the inheriting class is 41 | * a server socket, this fields contain the address and the port to which the 42 | * server is bound. 43 | * 44 | * The getters, gethost() and getport() may be used for a 45 | * server application to get the paramters of the remote peer. 46 | */ 47 | 48 | #include 49 | 50 | namespace libsocket { 51 | using std::string; 52 | 53 | inet_socket::inet_socket() : host(""), port("") {} 54 | 55 | /** 56 | * For sockets behaving as client: Returns the remote host. 57 | * For sockets behaving as server: Returns the address bound to. 58 | */ 59 | const string& inet_socket::gethost(void) const { return host; } 60 | 61 | /** 62 | * For sockets behaving as client: Returns the remote port. 63 | * For sockets behaving as server: Returns the port bound to. 64 | */ 65 | const string& inet_socket::getport(void) const { return port; } 66 | } // namespace libsocket 67 | -------------------------------------------------------------------------------- /C++/inetclientdgram.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // oo wrapper around libinetsocket 11 | /* 12 | The committers of the libsocket project, all rights reserved 13 | (c) 2012, dermesser 14 | 15 | Redistribution and use in source and binary forms, with or without 16 | modification, are permitted provided that the following conditions are met: 17 | 18 | 1. Redistributions of source code must retain the above copyright notice, 19 | this list of conditions and the following disclaimer. 20 | 2. Redistributions in binary form must reproduce the above copyright notice, 21 | this list of conditions and the following disclaimer in the documentation 22 | and/or other materials provided with the distribution. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | 35 | */ 36 | 37 | /** 38 | * @file inetclientdgram.cpp 39 | * @brief Class for connectable UDP sockets 40 | * 41 | * This file provides the class inet_dgram_client which is used 42 | * for internet domain UDP client sockets. You think, in UDP 43 | * there is no difference between client and server? This is 44 | * correct, but in libsocket, the difference is that the UDP 45 | * client sockets may be connected and are not explicitly 46 | * bound to somewhere. 47 | */ 48 | 49 | #include 50 | #include 51 | #include 52 | 53 | #include 54 | #ifndef SOCK_NONBLOCK 55 | #define SOCK_NONBLOCK O_NONBLOCK 56 | #endif 57 | 58 | namespace libsocket { 59 | using std::string; 60 | 61 | // Constructors 62 | 63 | /** 64 | * @brief Create normal datagram socket (connectable). 65 | * 66 | * @param proto_osi3 `LIBSOCKET_IPv4` or `LIBSOCKET_IPv6` or `LIBSOCKET_BOTH` 67 | * @param flags Flags for `socket(2)`. 68 | */ 69 | inet_dgram_client::inet_dgram_client(int proto_osi3, int flags) { 70 | setup(proto_osi3, flags); 71 | } 72 | 73 | /** 74 | * @brief Create datagram socket and connect it immediately to the given host 75 | * and port. 76 | * 77 | * @param dsthost Remote host name 78 | * @param dstport Remote port 79 | * @param proto_osi3 `LIBSOCKET_IPv4` or `LIBSOCKET_IPv6` or `LIBSOCKET_BOTH` 80 | * @param flags Flags for `socket(2)` 81 | */ 82 | inet_dgram_client::inet_dgram_client(const char* dsthost, const char* dstport, 83 | int proto_osi3, int flags) { 84 | setup(dsthost, dstport, proto_osi3, flags); 85 | } 86 | 87 | /** 88 | * @brief Create datagram socket and connect it immediately to the given host 89 | * and port. 90 | * 91 | * @param dsthost Remote host name 92 | * @param dstport Remote port 93 | * @param proto_osi3 `LIBSOCKET_IPv4` or `LIBSOCKET_IPv6` or `LIBSOCKET_BOTH` 94 | * @param flags Flags for `socket(2)` 95 | */ 96 | inet_dgram_client::inet_dgram_client(const string& dsthost, 97 | const string& dstport, int proto_osi3, 98 | int flags) { 99 | setup(dsthost, dstport, proto_osi3, flags); 100 | } 101 | 102 | /** 103 | * @brief Set up normal datagram socket (connectable). [NOT FOR EXTERNAL USE] 104 | * 105 | * @param proto_osi3 `LIBSOCKET_IPv4` or `LIBSOCKET_IPv6` or `LIBSOCKET_BOTH` 106 | * @param flags Flags for `socket(2)`. 107 | */ 108 | void inet_dgram_client::setup(int proto_osi3, int flags) { 109 | if (-1 == (sfd = create_inet_dgram_socket(proto_osi3, flags))) 110 | throw socket_exception(__FILE__, __LINE__, 111 | "inet_dgram_client::inet_dgram_client() - Could " 112 | "not create inet dgram socket!"); 113 | proto = proto_osi3; 114 | 115 | is_nonblocking = flags & SOCK_NONBLOCK; 116 | } 117 | 118 | /** 119 | * @brief Set up datagram socket and connect it immediately to the given host 120 | * and port. [NOT FOR EXTERNAL USE] 121 | * 122 | * @param dsthost Remote host name 123 | * @param dstport Remote port 124 | * @param proto_osi3 `LIBSOCKET_IPv4` or `LIBSOCKET_IPv6` or `LIBSOCKET_BOTH` 125 | * @param flags Flags for `socket(2)` 126 | */ 127 | void inet_dgram_client::setup(const char* dsthost, const char* dstport, 128 | int proto_osi3, int flags) { 129 | // Retrieve address family 130 | if (proto_osi3 == LIBSOCKET_BOTH) proto_osi3 = get_address_family(dsthost); 131 | 132 | if (-1 == (sfd = create_inet_dgram_socket(proto_osi3, flags))) 133 | throw socket_exception(__FILE__, __LINE__, 134 | "inet_dgram_client::inet_dgram_client() - Could " 135 | "not create inet dgram socket!"); 136 | 137 | inet_dgram_client::connect(dsthost, dstport); 138 | 139 | proto = proto_osi3; 140 | is_nonblocking = flags & SOCK_NONBLOCK; 141 | } 142 | 143 | /** 144 | * @brief Set up datagram socket and connect it immediately to the given host 145 | * and port. [NOT FOR EXTERNAL USE] 146 | * 147 | * @param dsthost Remote host name 148 | * @param dstport Remote port 149 | * @param proto_osi3 `LIBSOCKET_IPv4` or `LIBSOCKET_IPv6` or `LIBSOCKET_BOTH` 150 | * @param flags Flags for `socket(2)` 151 | */ 152 | void inet_dgram_client::setup(const string& dsthost, const string& dstport, 153 | int proto_osi3, int flags) { 154 | setup(dsthost.c_str(), dstport.c_str(), proto_osi3, flags); 155 | } 156 | 157 | /** 158 | * @brief Connect datagram socket. 159 | * 160 | * Connect a datagram socket to a remote peer so only its packets are received 161 | * and all data written is sent to it. 162 | * 163 | * @param dsthost Destination host 164 | * @param dstport Destination port 165 | */ 166 | void inet_dgram_client::connect(const char* dsthost, const char* dstport) { 167 | if (sfd == -1) 168 | throw socket_exception( 169 | __FILE__, __LINE__, 170 | "inet_dgram_client::connect() - Socket has already been closed!", 171 | false); 172 | if (-1 == (connect_inet_dgram_socket(sfd, dsthost, dstport))) 173 | throw socket_exception( 174 | __FILE__, __LINE__, 175 | "inet_dgram_client::connect() - Could not connect dgram socket! " 176 | "(Maybe this socket has a wrong address family?)"); 177 | 178 | host = dsthost; 179 | port = dstport; 180 | connected = true; 181 | } 182 | 183 | /** 184 | * @brief Connect datagram socket. 185 | * 186 | * Connect a datagram socket to a remote peer so only its packets are received 187 | * and all data written is sent to it. 188 | * 189 | * @param dsthost Destination host 190 | * @param dstport Destination port 191 | */ 192 | void inet_dgram_client::connect(const string& dsthost, const string& dstport) { 193 | if (sfd == -1) 194 | throw socket_exception( 195 | __FILE__, __LINE__, 196 | "inet_dgram_client::connect() - Socket has already been closed!", 197 | false); 198 | if (-1 == 199 | (connect_inet_dgram_socket(sfd, dsthost.c_str(), dstport.c_str()))) 200 | throw socket_exception( 201 | __FILE__, __LINE__, 202 | "inet_dgram_client::connect() - Could not connect dgram socket! " 203 | "(Maybe this socket has a wrong address family?)"); 204 | 205 | host = dsthost; 206 | port = dstport; 207 | connected = true; 208 | } 209 | 210 | /* 211 | * @brief Break association to host. Does not close the socket. 212 | * 213 | * *Should actually be called 'disconnect'* 214 | * 215 | */ 216 | void inet_dgram_client::deconnect(void) { 217 | if (-1 == (connect_inet_dgram_socket(sfd, NULL, NULL))) 218 | throw socket_exception( 219 | __FILE__, __LINE__, 220 | "inet_dgram_client::deconnect() - Could not disconnect!"); 221 | 222 | connected = false; 223 | host.clear(); 224 | port.clear(); 225 | } 226 | } // namespace libsocket 227 | -------------------------------------------------------------------------------- /C++/inetclientstream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | /* 10 | The committers of the libsocket project, all rights reserved 11 | (c) 2012, dermesser 12 | 13 | Redistribution and use in source and binary forms, with or without 14 | modification, are permitted provided that the following conditions are met: 15 | 16 | 1. Redistributions of source code must retain the above copyright notice, 17 | this list of conditions and the following disclaimer. 18 | 2. Redistributions in binary form must reproduce the above copyright notice, 19 | this list of conditions and the following disclaimer in the documentation 20 | and/or other materials provided with the distribution. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 23 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 26 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | */ 34 | 35 | /** 36 | * @file inetclientstream.cpp 37 | * @brief TCP/IP socket class. 38 | * 39 | * inetclientstream.cpp provides the class inet_stream 40 | * (which should actually be called inet_stream_client). 41 | * This class is used to communicate with TCP servers, 42 | * like HTTP-, SMTP-, POP3-, FTP-, telnet-Servers. 43 | * 44 | * The I/O abilities are inherited from stream_client_socket. 45 | */ 46 | 47 | #include 48 | #include 49 | #include 50 | 51 | namespace libsocket { 52 | using std::string; 53 | 54 | /// Void constructor; call connect() before using the socket! 55 | inet_stream::inet_stream(void) {} 56 | 57 | /** 58 | * @brief Connecting constructor 59 | * 60 | * Creates TCP/IP client socket and connects. 61 | * 62 | * @param dsthost Remote host 63 | * @param dstport Remote port 64 | * @param proto_osi3 `LIBSOCKET_IPv4` or `LIBSOCKET_IPv6` or `LIBSOCKET_BOTH` 65 | * @param flags Flags for `socket(2)` 66 | */ 67 | inet_stream::inet_stream(const char* dsthost, const char* dstport, 68 | int proto_osi3, int flags) { 69 | connect(dsthost, dstport, proto_osi3, flags); 70 | } 71 | 72 | /** 73 | * @brief Connecting constructor 74 | * 75 | * Creates TCP/IP client socket and connects. 76 | * 77 | * @param dsthost Remote host 78 | * @param dstport Remote port 79 | * @param proto_osi3 `LIBSOCKET_IPv4` or `LIBSOCKET_IPv6` or `LIBSOCKET_BOTH` 80 | * @param flags Flags for `socket(2)` 81 | */ 82 | inet_stream::inet_stream(const string& dsthost, const string& dstport, 83 | int proto_osi3, int flags) { 84 | connect(dsthost.c_str(), dstport.c_str(), proto_osi3, flags); 85 | } 86 | 87 | /** 88 | * @brief Set up socket if not already done. 89 | * 90 | * Creates TCP/IP client socket and connects. Fails if the socket is already set 91 | * up. 92 | * 93 | * @param dsthost Remote host 94 | * @param dstport Remote port 95 | * @param proto_osi3 `LIBSOCKET_IPv4` or `LIBSOCKET_IPv6` or `LIBSOCKET_BOTH` 96 | * @param flags Flags for `socket(2)` 97 | */ 98 | void inet_stream::connect(const char* dsthost, const char* dstport, 99 | int proto_osi3, int flags) { 100 | if (sfd != -1) 101 | throw socket_exception(__FILE__, __LINE__, 102 | "inet_stream::connect() - Already connected!", 103 | false); 104 | 105 | sfd = create_inet_stream_socket(dsthost, dstport, proto_osi3, flags); 106 | 107 | if (sfd < 0) 108 | throw socket_exception( 109 | __FILE__, __LINE__, 110 | "inet_stream::connect() - Could not create socket"); 111 | 112 | host = dsthost; 113 | port = dstport; 114 | proto = proto_osi3; 115 | 116 | // New file descriptor, therefore reset shutdown flags 117 | shut_rd = false; 118 | shut_wr = false; 119 | } 120 | 121 | /** 122 | * @brief Set up socket if not already done. 123 | * 124 | * Creates TCP/IP client socket and connects. Fails if the socket is already set 125 | * up. 126 | * 127 | * @param dsthost Remote host 128 | * @param dstport Remote port 129 | * @param proto_osi3 `LIBSOCKET_IPv4` or `LIBSOCKET_IPv6` or `LIBSOCKET_BOTH` 130 | * @param flags Flags for `socket(2)` 131 | */ 132 | void inet_stream::connect(const string& dsthost, const string& dstport, 133 | int proto_osi3, int flags) { 134 | connect(dsthost.c_str(), dstport.c_str(), proto_osi3, flags); 135 | } 136 | } // namespace libsocket 137 | -------------------------------------------------------------------------------- /C++/inetserverdgram.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | The committers of the libsocket project, all rights reserved 6 | (c) 2012, dermesser 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | 11 | 1. Redistributions of source code must retain the above copyright notice, 12 | this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | */ 29 | 30 | /** 31 | * @file inetserverdgram.cpp 32 | * @brief Contains class for creating a bound datagram socket. 33 | * 34 | * inet_dgram_server provides nothing more than a constructor 35 | * which binds the UDP socket to the specified host. Everything 36 | * other, e.g. the I/O functions like rcvfrom and sndto are 37 | * inherited from inet_dgram. 38 | */ 39 | 40 | #include 41 | #include 42 | #include 43 | 44 | #include 45 | #ifndef SOCK_NONBLOCK 46 | #define SOCK_NONBLOCK O_NONBLOCK 47 | #endif 48 | 49 | namespace libsocket { 50 | using std::string; 51 | 52 | /** 53 | * @brief Create datagram socket and bind it. 54 | * 55 | * @param host Bind address (Wildcard: "0.0.0.0"/"::") 56 | * @param port Bind port 57 | * @param proto_osi3 `LIBSOCKET_IPv4` or `LIBSOCKET_IPv6` or `LIBSOCKET_BOTH` 58 | * @param flags Flags for `socket(2)` 59 | */ 60 | inet_dgram_server::inet_dgram_server(const char* host, const char* port, 61 | int proto_osi3, int flags) { 62 | setup(host, port, proto_osi3, flags); 63 | } 64 | 65 | /** 66 | * @brief Create datagram socket and bind it. 67 | * 68 | * @param host Bind address (Wildcard: "0.0.0.0"/"::") 69 | * @param port Bind port 70 | * @param proto_osi3 `LIBSOCKET_IPv4` or `LIBSOCKET_IPv6` or `LIBSOCKET_BOTH` 71 | * @param flags Flags for `socket(2)` 72 | */ 73 | inet_dgram_server::inet_dgram_server(const string& host, const string& port, 74 | int proto_osi3, int flags) { 75 | setup(host, port, proto_osi3, flags); 76 | } 77 | 78 | /** 79 | * @brief Set up socket. **NOT FOR EXTERNAL USE** 80 | * 81 | * @param bhost Bind address (Wildcard: "0.0.0.0"/"::") 82 | * @param bport Bind port 83 | * @param proto_osi3 `LIBSOCKET_IPv4` or `LIBSOCKET_IPv6` or `LIBSOCKET_BOTH` 84 | * @param flags Flags for `socket(2)` 85 | */ 86 | void inet_dgram_server::setup(const char* bhost, const char* bport, 87 | int proto_osi3, int flags) { 88 | // No separate call to get_address_family() 89 | 90 | if (-1 == (sfd = create_inet_server_socket(bhost, bport, LIBSOCKET_UDP, 91 | proto_osi3, flags))) 92 | throw socket_exception(__FILE__, __LINE__, 93 | "inet_dgram_server::inet_dgram_server() - could " 94 | "not create server socket!"); 95 | 96 | host = string(bhost); 97 | port = string(bport); 98 | is_nonblocking = flags & SOCK_NONBLOCK; 99 | } 100 | 101 | /** 102 | * @brief Set up socket. **NOT FOR EXTERNAL USE** 103 | * 104 | * @param bhost Bind address (Wildcard: "0.0.0.0"/"::") 105 | * @param bport Bind port 106 | * @param proto_osi3 `LIBSOCKET_IPv4` or `LIBSOCKET_IPv6` or `LIBSOCKET_BOTH` 107 | * @param flags Flags for `socket(2)` 108 | */ 109 | void inet_dgram_server::setup(const string& bhost, const string& bport, 110 | int proto_osi3, int flags) { 111 | setup(bhost.c_str(), bport.c_str(), proto_osi3, flags); 112 | } 113 | } // namespace libsocket 114 | -------------------------------------------------------------------------------- /C++/select.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The committers of the libsocket project, all rights reserved 3 | (c) 2012, dermesser 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 15 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 18 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | */ 26 | 27 | /** 28 | * @file select.cpp 29 | * 30 | * @brief Contains non-template pieces of the select logic. 31 | */ 32 | 33 | #include 34 | #include 35 | 36 | namespace libsocket { 37 | /***** UTIL *****/ 38 | /** 39 | * @brief Utility function to find the highest number in a vector (typically, 40 | * the highest file descriptor) 41 | */ 42 | int highestfd(const std::vector& v) { 43 | std::vector::const_iterator end = v.end(); 44 | int highestfd = 0; 45 | 46 | for (std::vector::const_iterator cur = v.begin(); cur != end; cur++) { 47 | if (*cur > highestfd) highestfd = *cur; 48 | } 49 | 50 | return highestfd; 51 | } 52 | 53 | } // namespace libsocket 54 | -------------------------------------------------------------------------------- /C++/socket.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | /* 3 | The committers of the libsocket project, all rights reserved 4 | (c) 2012, dermesser 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | */ 27 | 28 | /** 29 | * @file socket.cpp 30 | * @brief The very base class of libsocket. 31 | * 32 | * Provides the basic socket functionality, like a field 33 | * for the file descriptor and the destructor respectively 34 | * a close()-wrapper destroy(). This is the root of the 35 | * class graph. 36 | */ 37 | 38 | #include 39 | 40 | namespace libsocket { 41 | /** 42 | * @brief Constructor. Sets `sfd` to -1. 43 | * 44 | */ 45 | socket::socket(void) 46 | : sfd(-1), is_nonblocking(false), close_on_destructor(true) {} 47 | 48 | /** 49 | * @brief Move constructor. 50 | */ 51 | socket::socket(socket&& other) 52 | : sfd(other.sfd), is_nonblocking(false), close_on_destructor(true) { 53 | other.sfd = -1; 54 | } 55 | 56 | /** 57 | * @brief Destructor: closes socket. 58 | */ 59 | socket::~socket(void) { 60 | /* 61 | * This is possible because socket::~socket(const socket&) is deleted. 62 | */ 63 | if (close_on_destructor) destroy(); 64 | } 65 | 66 | /** 67 | * @brief Destroys a socket. 68 | * 69 | * @retval 0 Fine! 70 | * @retval <0 Most likely the socket was already closed before. 71 | */ 72 | int socket::destroy(void) { 73 | if (0 > sfd) return 0; 74 | 75 | if (0 > close(sfd)) return -1; 76 | 77 | sfd = -1; 78 | 79 | return 0; 80 | } 81 | 82 | /** 83 | * @brief Returns the socket file descriptor. 84 | * 85 | * @return The socket file descriptor of the class. 86 | * 87 | * getfd() is a getter you may use to obtain the file descriptor 88 | * for raw operations on it. It's relatively uncritical as libsocket 89 | * just wraps other syscalls and doesn't manipulate it using unusual ways. 90 | */ 91 | int socket::getfd(void) const { return sfd; } 92 | 93 | /** 94 | * @brief Set socket options on the underlying socket. 95 | * 96 | * @return The return value of setsockopt(2). 97 | * 98 | * Sets socket options using setsockopt(2). See setsockopt(2), tcp(7), udp(7), 99 | * unix(7) for documentation on how to use this function. 100 | */ 101 | int socket::set_sock_opt(int level, int optname, const char* optval, 102 | socklen_t optlen) const { 103 | return setsockopt(sfd, level, optname, optval, optlen); 104 | } 105 | } // namespace libsocket 106 | -------------------------------------------------------------------------------- /C++/unixbase.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 6 | The committers of the libsocket project, all rights reserved 7 | (c) 2012, dermesser 8 | 9 | Redistribution and use in source and binary forms, with or without 10 | modification, are permitted provided that the following conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright notice, 13 | this list of conditions and the following disclaimer. 14 | 2. Redistributions in binary form must reproduce the above copyright notice, 15 | this list of conditions and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 19 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 22 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | */ 30 | 31 | /** 32 | * @file unixbase.cpp 33 | * @brief Base class for all unix sockets 34 | * 35 | * Provides only the field bindpath for every UNIX socket classes. 36 | * This is particularly used for the UNIX datagram sockets which 37 | * may be bound, both client and server. 38 | */ 39 | 40 | #include 41 | 42 | namespace libsocket { 43 | using std::string; 44 | 45 | unix_socket::unix_socket(void) : _path("") {} 46 | 47 | /** 48 | * @brief Returns the path we're bound or connected to 49 | */ 50 | string unix_socket::get_path(void) { return _path; } 51 | } // namespace libsocket 52 | -------------------------------------------------------------------------------- /C++/unixclientdgram.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using std::string; 4 | 5 | /* 6 | The committers of the libsocket project, all rights reserved 7 | (c) 2012, dermesser 8 | 9 | Redistribution and use in source and binary forms, with or without 10 | modification, are permitted provided that the following conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright notice, 13 | this list of conditions and the following disclaimer. 14 | 2. Redistributions in binary form must reproduce the above copyright notice, 15 | this list of conditions and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 19 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 22 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | */ 30 | 31 | /** 32 | * @file unixclientdgram.cpp 33 | * @brief Client for UNIX domain datagram sockets. 34 | * 35 | * An important difference to inet_dgram_client is that the 36 | * path given at the constructors is the /bind path/, not 37 | * a socket to which the datagram is connected immediately 38 | * after creation. 39 | * 40 | */ 41 | 42 | #include 43 | #include 44 | #include 45 | 46 | #include 47 | #ifndef SOCK_NONBLOCK 48 | #define SOCK_NONBLOCK O_NONBLOCK 49 | #endif 50 | 51 | namespace libsocket { 52 | /** 53 | * @brief Set a UNIX domain datagram socket up 54 | * 55 | * @param path The path to bind this socket to 56 | * @param flags Flags for `socket(2)` 57 | */ 58 | void unix_dgram_client::setup(const char* path, int flags) { 59 | if (sfd != -1) 60 | throw socket_exception(__FILE__, __LINE__, 61 | "unix_dgram_client::unix_dgram_client: Socket " 62 | "has already been set up!", 63 | false); 64 | 65 | sfd = create_unix_dgram_socket(path, flags); 66 | 67 | if (sfd < 0) 68 | throw socket_exception(__FILE__, __LINE__, 69 | "unix_dgram_client::unix_dgram_client: Could " 70 | "not create unix dgram client socket!"); 71 | 72 | if (path) _path.assign(path); 73 | 74 | is_nonblocking = flags & SOCK_NONBLOCK; 75 | } 76 | 77 | /** 78 | * @brief Constructor with only `socket()` flags 79 | * 80 | * @param flags Flags for `socket(2)` 81 | */ 82 | unix_dgram_client::unix_dgram_client(int flags) { 83 | setup(NULL, flags); // bind to nowhere 84 | } 85 | 86 | /** 87 | * @brief Constructor setting the socket up 88 | * 89 | * This constructor binds the socket to the given path. 90 | * 91 | * @param path Bind path. 92 | * @param flags Flags for `socket(2)` 93 | */ 94 | unix_dgram_client::unix_dgram_client(const char* path, int flags) { 95 | setup(path, flags); // bind to path 96 | } 97 | 98 | /** 99 | * @brief Constructor setting the socket up 100 | * 101 | * This constructor binds the socket to the given path. 102 | * 103 | * @param path Bind path. 104 | * @param flags Flags for `socket(2)` 105 | */ 106 | unix_dgram_client::unix_dgram_client(const string& path, int flags) { 107 | setup(path.c_str(), flags); 108 | } 109 | 110 | /** 111 | * @brief Connect a UNIX datagram socket 112 | * 113 | * This function connects a datagram socket; `connect(2)` says the following 114 | * about this: 115 | * 116 | * > If the socket sockfd is of type SOCK_DGRAM then addr is the address to 117 | * which datagrams are sent by default, and the only address from which 118 | * datagrams are received. 119 | * 120 | * @param path The path of the socket to connect this socket to. 121 | */ 122 | void unix_dgram_client::connect(const char* path) { 123 | if (sfd == -1) 124 | throw socket_exception( 125 | __FILE__, __LINE__, 126 | "unix_dgram_client::connect() - Socket has already been closed!", 127 | false); 128 | if (connect_unix_dgram_socket(sfd, path) < 0) 129 | throw socket_exception( 130 | __FILE__, __LINE__, 131 | "unix_dgram_client::connect: Could not connect dgram socket!"); 132 | 133 | _path.assign(path); 134 | 135 | connected = true; 136 | } 137 | 138 | /** 139 | * @brief Connect a UNIX datagram socket 140 | * 141 | * This function connects a datagram socket; `connect(2)` says the following 142 | * about this: 143 | * 144 | * > If the socket sockfd is of type SOCK_DGRAM then addr is the address to 145 | * which datagrams are sent by default, and the only address from which 146 | * datagrams are received. 147 | * 148 | * @param path The path of the socket to connect this socket to. 149 | */ 150 | void unix_dgram_client::connect(const string& path) { connect(path.c_str()); } 151 | 152 | /** 153 | * @brief Disconnect a UNIX datagram socket 154 | * 155 | * Disconnects a previously connected socket. 156 | * 157 | */ 158 | void unix_dgram_client::deconnect(void) { 159 | if (connect_unix_dgram_socket(sfd, 0) < 0) 160 | throw socket_exception( 161 | __FILE__, __LINE__, 162 | "unix_dgram_client::deconnect: Could not disconnect dgram socket!"); 163 | 164 | _path.clear(); 165 | 166 | connected = false; 167 | } 168 | } // namespace libsocket 169 | -------------------------------------------------------------------------------- /C++/unixclientstream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | /* 9 | The committers of the libsocket project, all rights reserved 10 | (c) 2012, dermesser 11 | 12 | Redistribution and use in source and binary forms, with or without 13 | modification, are permitted provided that the following conditions are met: 14 | 15 | 1. Redistributions of source code must retain the above copyright notice, 16 | this list of conditions and the following disclaimer. 17 | 2. Redistributions in binary form must reproduce the above copyright notice, 18 | this list of conditions and the following disclaimer in the documentation 19 | and/or other materials provided with the distribution. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 22 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 25 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | */ 33 | 34 | /** 35 | * @file unixclientstream.cpp 36 | * @brief Contains `unix_stream_client`, which can be used for UNIX SOCK_STREAM 37 | * connections. 38 | * 39 | * unix_stream_client is the client socket 40 | * for UNIX domain SOCK_STREAM client sockets. 41 | * You may create and connect the socket after 42 | * instantiation using connect(). 43 | */ 44 | 45 | #include 46 | #include 47 | #include 48 | 49 | namespace libsocket { 50 | using std::string; 51 | 52 | /** 53 | * @brief Constructor. 54 | */ 55 | unix_stream_client::unix_stream_client(void) {} 56 | 57 | /** 58 | * @brief Constructor, setting up a connection 59 | * 60 | * Constructs a UNIX stream client socket and connects it. 61 | * 62 | * @param path Peer (server) socket. 63 | * @param socket_flags Flags for `socket(2)` 64 | */ 65 | unix_stream_client::unix_stream_client(const char* path, int socket_flags) { 66 | connect(path, socket_flags); 67 | } 68 | 69 | /** 70 | * @brief Constructor, setting up a connection 71 | * 72 | * Constructs a UNIX stream client socket and connects it. 73 | * 74 | * @param path Peer (server) socket. 75 | * @param socket_flags Flags for `socket(2)` 76 | */ 77 | unix_stream_client::unix_stream_client(const string& path, int socket_flags) { 78 | connect(path.c_str(), socket_flags); 79 | } 80 | 81 | /** 82 | * @brief Connect socket 83 | * 84 | * Connects a client stream socket. 85 | * 86 | * @param path The server socket's path 87 | * @param socket_flags Flags for `socket(2)` (Do I repeat myself?) 88 | */ 89 | void unix_stream_client::connect(const char* path, int socket_flags) { 90 | if (sfd != -1) 91 | throw socket_exception( 92 | __FILE__, __LINE__, 93 | "unix_stream_client::connect: Already connected!", false); 94 | 95 | sfd = create_unix_stream_socket(path, socket_flags); 96 | 97 | _path.assign(path); 98 | 99 | if (sfd < 0) 100 | throw socket_exception(__FILE__, __LINE__, 101 | "unix_stream_client::unix_stream_client: Could " 102 | "not create and connect UNIX socket!"); 103 | 104 | // New file descriptor, therefore reset shutdown flags 105 | shut_rd = false; 106 | shut_wr = false; 107 | } 108 | 109 | /** 110 | * @brief Connect socket 111 | * 112 | * Connects a client stream socket. 113 | * 114 | * @param path The server socket's path 115 | * @param socket_flags Flags for `socket(2)` (Do I repeat myself?) 116 | */ 117 | void unix_stream_client::connect(const string& path, int socket_flags) { 118 | connect(path.c_str(), socket_flags); 119 | } 120 | } // namespace libsocket 121 | -------------------------------------------------------------------------------- /C++/unixdgram.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | /* 8 | The committers of the libsocket project, all rights reserved 9 | (c) 2012, dermesser 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | 14 | 1. Redistributions of source code must retain the above copyright notice, 15 | this list of conditions and the following disclaimer. 16 | 2. Redistributions in binary form must reproduce the above copyright notice, 17 | this list of conditions and the following disclaimer in the documentation 18 | and/or other materials provided with the distribution. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 21 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 24 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 27 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | /** 34 | * @file unixdgram.cpp 35 | * @brief I/O for UNIX sockets 36 | * 37 | * Provides the basic I/O functions for every UNIX domain 38 | * datagram socket. Every unix datagram socket class is 39 | * derived from this class because sndto and rcvfrom may be 40 | * called on every datagram socket. 41 | */ 42 | 43 | #include 44 | #include 45 | #include 46 | 47 | namespace libsocket { 48 | /** 49 | * @brief Send data to datagram socket 50 | * 51 | * @param buf Pointer to data. 52 | * @param length Length of `buf` 53 | * @param path Path of destination 54 | * @param sendto_flags Flags for `sendto(2)` 55 | * 56 | * @returns How many bytes were sent. Returns -1 if the socket was created with 57 | * SOCK_NONBLOCK and errno is EWOULDBLOCK. 58 | */ 59 | ssize_t unix_dgram::sndto(const void* buf, size_t length, const char* path, 60 | int sendto_flags) { 61 | if (buf == NULL) 62 | throw socket_exception(__FILE__, __LINE__, 63 | "unix_dgram::sndto: Buffer is NULL!", false); 64 | 65 | ssize_t bytes; 66 | 67 | if (0 > (bytes = sendto_unix_dgram_socket(sfd, buf, length, path, 68 | sendto_flags))) { 69 | if (is_nonblocking && errno == EWOULDBLOCK) 70 | return -1; 71 | else 72 | throw socket_exception( 73 | __FILE__, __LINE__, 74 | "unix_dgram::sndto: Could not send data to peer!"); 75 | } 76 | 77 | return bytes; 78 | } 79 | 80 | /** 81 | * @brief Send data to datagram socket 82 | * 83 | * @param buf Pointer to data. 84 | * @param length Length of `buf` 85 | * @param path Path of destination 86 | * @param sendto_flags Flags for `sendto(2)` 87 | * 88 | * @returns How many bytes were sent. Returns -1 if the socket was created with 89 | * SOCK_NONBLOCK and errno is EWOULDBLOCK. 90 | */ 91 | ssize_t unix_dgram::sndto(const void* buf, size_t length, const string& path, 92 | int sendto_flags) { 93 | return sndto(buf, length, path.c_str(), sendto_flags); 94 | } 95 | 96 | /** 97 | * @brief Send data to datagram socket 98 | * 99 | * @param buf Pointer to data. 100 | * @param path Path of destination 101 | * @param sendto_flags Flags for `sendto(2)` 102 | * 103 | * @returns How many bytes were sent. Returns -1 if the socket was created with 104 | * SOCK_NONBLOCK and errno is EWOULDBLOCK. 105 | */ 106 | ssize_t unix_dgram::sndto(const string& buf, const string& path, 107 | int sendto_flags) { 108 | return sndto(static_cast(buf.c_str()), buf.size(), 109 | path.c_str(), sendto_flags); 110 | } 111 | 112 | /** 113 | * @brief Receive data and store the sender's address 114 | * 115 | * @param buf Receive buffer 116 | * @param length Length of `buf` 117 | * @param source Buffer for sender's path 118 | * @param source_len `source`'s length 119 | * @param recvfrom_flags Flags for `recvfrom(2)` 120 | * 121 | * @returns How many bytes were received. Returns -1 if the socket was created 122 | * with SOCK_NONBLOCK and errno is EWOULDBLOCK. 123 | */ 124 | ssize_t unix_dgram::rcvfrom(void* buf, size_t length, char* source, 125 | size_t source_len, int recvfrom_flags) { 126 | if (buf == NULL) 127 | throw socket_exception(__FILE__, __LINE__, 128 | "unix_dgram::rcvfrom: Buffer is NULL!", false); 129 | 130 | ssize_t bytes; 131 | 132 | bytes = recvfrom_unix_dgram_socket(sfd, buf, length, source, source_len, 133 | recvfrom_flags); 134 | 135 | if (bytes < 0) { 136 | if (is_nonblocking && errno == EWOULDBLOCK) 137 | return -1; 138 | else 139 | throw socket_exception( 140 | __FILE__, __LINE__, 141 | "unix_dgram::rcvfrom: Could not receive data from peer!"); 142 | } 143 | 144 | return bytes; 145 | } 146 | 147 | /** 148 | * @brief Receive data and store the sender's address 149 | * 150 | * @param buf Receive buffer 151 | * @param length Length of `buf` 152 | * @param source Buffer for sender's path. The path is truncated to 153 | * `source.size()` characters. 154 | * @param recvfrom_flags Flags for `recvfrom(2)` 155 | * 156 | * @returns How many bytes were received. Returns -1 if the socket was created 157 | * with SOCK_NONBLOCK and errno is EWOULDBLOCK. 158 | */ 159 | ssize_t unix_dgram::rcvfrom(void* buf, size_t length, string& source, 160 | int recvfrom_flags) { 161 | if (buf == NULL) 162 | throw socket_exception(__FILE__, __LINE__, 163 | "unix_dgram::rcvfrom: Buffer is NULL!", false); 164 | 165 | ssize_t bytes; 166 | 167 | using std::unique_ptr; 168 | 169 | unique_ptr source_cstr( 170 | new char[108]); // AFAIK, the address field in struct sockaddr_un is 171 | // only 108 bytes long... 172 | size_t source_cstr_len; 173 | 174 | memset(source_cstr.get(), 0, 108); 175 | 176 | bytes = recvfrom_unix_dgram_socket(sfd, buf, length, source_cstr.get(), 107, 177 | recvfrom_flags); 178 | 179 | if (bytes < 0) { 180 | if (is_nonblocking && errno == EWOULDBLOCK) 181 | return -1; 182 | else 183 | throw socket_exception( 184 | __FILE__, __LINE__, 185 | "unix_dgram::rcvfrom: Could not receive data from peer!"); 186 | } 187 | 188 | source_cstr_len = strlen(source_cstr.get()); 189 | 190 | source.resize(source_cstr_len); 191 | 192 | source = source_cstr.get(); 193 | 194 | return bytes; 195 | } 196 | 197 | /** 198 | * @brief Receive data and store the sender's address 199 | * 200 | * @param buf Receive buffer. The data is truncated to `buf.size()` characters. 201 | * @param source Buffer for sender's path. The path is truncated to 202 | * `source.size()` characters. 203 | * @param recvfrom_flags Flags for `recvfrom(2)` 204 | * 205 | * @returns How many bytes were received. Returns -1 if the socket was created 206 | * with SOCK_NONBLOCK and errno is EWOULDBLOCK. 207 | */ 208 | ssize_t unix_dgram::rcvfrom(string& buf, string& source, int recvfrom_flags) { 209 | if (buf.empty()) 210 | throw socket_exception(__FILE__, __LINE__, 211 | "unix_dgram::rcvfrom: Buffer is empty!", false); 212 | 213 | ssize_t bytes; 214 | 215 | using std::unique_ptr; 216 | 217 | unique_ptr source_cstr( 218 | new char[108]); // AFAIK, the address field in struct sockaddr_un is 219 | // only 108 bytes... 220 | unique_ptr cbuf(new char[buf.size()]); 221 | 222 | size_t source_cstr_len; 223 | 224 | memset(source_cstr.get(), 0, 108); 225 | 226 | bytes = recvfrom_unix_dgram_socket(sfd, cbuf.get(), buf.size(), 227 | source_cstr.get(), 107, recvfrom_flags); 228 | 229 | if (bytes < 0) { 230 | if (is_nonblocking && errno == EWOULDBLOCK) 231 | return -1; 232 | else 233 | throw socket_exception( 234 | __FILE__, __LINE__, 235 | "unix_dgram::rcvfrom: Could not receive data from peer!"); 236 | } 237 | 238 | source_cstr_len = strlen(source_cstr.get()); 239 | 240 | source.resize(source_cstr_len); 241 | buf.resize(bytes); 242 | 243 | buf.assign(cbuf.get(), bytes); 244 | source.assign(source_cstr.get(), source_cstr_len); 245 | 246 | return bytes; 247 | } 248 | } // namespace libsocket 249 | -------------------------------------------------------------------------------- /C++/unixserverdgram.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | /* 7 | The committers of the libsocket project, all rights reserved 8 | (c) 2012, dermesser 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | 1. Redistributions of source code must retain the above copyright notice, 14 | this list of conditions and the following disclaimer. 15 | 2. Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | */ 31 | 32 | /** 33 | * @file unixserverdgram.cpp 34 | * @brief Class for UNIX domain datagram servers 35 | * 36 | * The only difference to "client" datagram socket is that this socket type is 37 | * not `connect()`-able. 38 | */ 39 | 40 | #include 41 | #include 42 | #include 43 | 44 | #include 45 | #ifndef SOCK_NONBLOCK 46 | #define SOCK_NONBLOCK O_NONBLOCK 47 | #endif 48 | 49 | namespace libsocket { 50 | using std::string; 51 | 52 | /** 53 | * @brief Void constructor. 54 | */ 55 | unix_dgram_server::unix_dgram_server(void) : bound(false) {} 56 | 57 | /** 58 | * @brief Constructs and binds a socket 59 | * 60 | * Constructs a socket and binds it to `bindpath`. Then calls `listen()`. 61 | * 62 | * @param bindpath Bind path. 63 | * @param socket_flags Flags for `socket(2)` 64 | */ 65 | unix_dgram_server::unix_dgram_server(const char* bindpath, int socket_flags) { 66 | setup(bindpath, socket_flags); 67 | } 68 | 69 | /** 70 | * @brief Constructs and binds a socket 71 | * 72 | * Constructs a socket and binds it to `bindpath`. Then calls `listen()`. 73 | * 74 | * @param bindpath Bind path. 75 | * @param socket_flags Flags for `socket(2)` 76 | */ 77 | unix_dgram_server::unix_dgram_server(const string& bindpath, int socket_flags) { 78 | setup(bindpath.c_str(), socket_flags); 79 | } 80 | 81 | /** 82 | * @brief Binds a socket 83 | * 84 | * Binds a socket. (Also calls `listen()`) 85 | * 86 | * @param bindpath Bind path. 87 | * @param socket_flags Flags for `socket(2)` 88 | */ 89 | void unix_dgram_server::setup(const char* bindpath, int socket_flags) { 90 | if (sfd != -1) 91 | throw socket_exception(__FILE__, __LINE__, 92 | "unix_dgram_server::setup: Already set up!", 93 | false); 94 | 95 | sfd = create_unix_server_socket(bindpath, LIBSOCKET_DGRAM, socket_flags); 96 | 97 | if (sfd < 0) 98 | throw socket_exception( 99 | __FILE__, __LINE__, 100 | "unix_dgram_server::setup: Could not create server!"); 101 | 102 | _path.assign(bindpath); 103 | bound = true; 104 | is_nonblocking = socket_flags & SOCK_NONBLOCK; 105 | } 106 | 107 | /** 108 | * @brief Binds a socket 109 | * 110 | * Binds a socket. (Also calls `listen()`) 111 | * 112 | * @param bindpath Bind path. 113 | * @param socket_flags Flags for `socket(2)` 114 | */ 115 | void unix_dgram_server::setup(const string& bindpath, int socket_flags) { 116 | setup(bindpath.c_str(), socket_flags); 117 | } 118 | } // namespace libsocket 119 | -------------------------------------------------------------------------------- /C++/unixserverstream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | /* 3 | The committers of the libsocket project, all rights reserved 4 | (c) 2012, dermesser 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | */ 27 | 28 | /** 29 | * @file unixserverstream.cpp 30 | * @brief Provides a UNIX domain STREAM server. 31 | * 32 | * The path given at the constructors is the bind 33 | * path. accept() accepts a new connection and returns 34 | * (like inet_stream_server) a pointer to a dynamically allocated 35 | * instance of unix_stream_client which may be used to 36 | * communicate with the connected client. 37 | */ 38 | 39 | #include 40 | #include 41 | #include 42 | 43 | namespace libsocket { 44 | using std::string; 45 | 46 | /** 47 | * @brief Void constructor 48 | */ 49 | unix_stream_server::unix_stream_server(void) {} 50 | 51 | /** 52 | * @brief Constructs and binds server socket. 53 | * 54 | * @param path Bind path. 55 | * @param flags Flags for `socket(2)` 56 | */ 57 | unix_stream_server::unix_stream_server(const char* path, int flags) { 58 | setup(path, flags); 59 | } 60 | 61 | /** 62 | * @brief Constructs and binds server socket. 63 | * 64 | * @param path Bind path. 65 | * @param flags Flags for `socket(2)` 66 | */ 67 | unix_stream_server::unix_stream_server(const string& path, int flags) { 68 | setup(path, flags); 69 | } 70 | 71 | /** 72 | * @brief Sets a server socket up. 73 | * 74 | * @param path Bind path. 75 | * @param flags Flags for `socket(2)` 76 | */ 77 | void unix_stream_server::setup(const char* path, int flags) { 78 | if (sfd != -1) 79 | throw socket_exception( 80 | __FILE__, __LINE__, 81 | "unix_stream_server::setup: Socket already set up!", false); 82 | if (path == NULL) 83 | throw socket_exception(__FILE__, __LINE__, 84 | "unix_stream_server::setup: Path is NULL!", 85 | false); 86 | 87 | sfd = create_unix_server_socket(path, LIBSOCKET_STREAM, flags); 88 | 89 | if (sfd < 0) 90 | throw socket_exception(__FILE__, __LINE__, 91 | "unix_stream_server::setup: Error at creating " 92 | "UNIX stream server socket!"); 93 | 94 | _path.assign(path); 95 | } 96 | 97 | /** 98 | * @brief Sets a server socket up. 99 | * 100 | * @param path Bind path. 101 | * @param flags Flags for `socket(2)` 102 | */ 103 | void unix_stream_server::setup(const string& path, int flags) { 104 | setup(path.c_str(), flags); 105 | } 106 | 107 | /** 108 | * @brief Accepts incoming connections on a UNIX domain stream server socket. 109 | * 110 | * @param flags Flags for Linux' `accept4()`; useless on other implementations. 111 | */ 112 | unix_stream_client* unix_stream_server::accept(int flags) { 113 | return accept2(flags).release(); 114 | } 115 | 116 | /** 117 | * @brief Accepts an incoming connection on a UNIX domain stream server socket 118 | * and returns an owned pointer. 119 | * 120 | * The owned pointer will be closed on destruction. 121 | * 122 | * @param flags Flags for `accept4()`; useless on other implementations. 123 | */ 124 | unique_ptr unix_stream_server::accept2(int flags) { 125 | int cfd; 126 | 127 | if (sfd == -1) 128 | throw socket_exception( 129 | __FILE__, __LINE__, 130 | "unix_stream_server::accept2: Socket not has not yet been set up!", false); 131 | 132 | unique_ptr client(new unix_stream_client); 133 | 134 | cfd = accept_unix_stream_socket(sfd, flags); 135 | 136 | if (cfd < 0) { 137 | if (is_nonblocking && errno == EWOULDBLOCK) 138 | return unique_ptr(nullptr); 139 | else 140 | throw socket_exception(__FILE__, __LINE__, 141 | "unix_stream_server::accept2: Error while " 142 | "accepting new connection!"); 143 | } 144 | 145 | client->sfd = cfd; 146 | 147 | return client; 148 | } 149 | } // namespace libsocket 150 | -------------------------------------------------------------------------------- /C/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | 3 | SET(libsocket_src 4 | ./inet/libinetsocket.c 5 | ./unix/libunixsocket.c 6 | ) 7 | 8 | IF ( NOT IS_SUNOS ) 9 | ADD_DEFINITIONS(-fPIC) # for the static library which needs to be linked into the shared libsocket++.so object. 10 | ADD_LIBRARY(socket_o OBJECT ${libsocket_src}) 11 | 12 | ADD_LIBRARY(socket_int STATIC $) #Static lib must be built for linking libsocket++ 13 | 14 | IF(BUILD_SHARED_LIBS) 15 | ADD_LIBRARY(socket SHARED $) 16 | 17 | INSTALL(TARGETS socket DESTINATION ${LIB_DIR}) 18 | ENDIF() 19 | 20 | 21 | IF(BUILD_STATIC_LIBS) 22 | SET_TARGET_PROPERTIES(socket_int PROPERTIES OUTPUT_NAME socket) 23 | INSTALL(TARGETS socket_int DESTINATION ${LIB_DIR}) 24 | ENDIF() 25 | ELSE() # On SunOS (e.g. OpenIndiana) we have to link against the system's libsocket. The library is renamed to libsocket_hl (hl = high-level) 26 | ADD_LIBRARY(socket_hl SHARED ${libsocket_src}) 27 | FIND_LIBRARY(solaris_socket_lib socket) 28 | TARGET_LINK_LIBRARIES(socket_hl ${solaris_socket_lib}) 29 | INSTALL(TARGETS socket_hl DESTINATION ${LIB_DIR}) 30 | ENDIF() 31 | 32 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(libsocket) 2 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 3 | 4 | # Header conf 5 | SET(VERSION 2.4) 6 | 7 | IF( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) 8 | SET(IS_FREEBSD 0) 9 | SET(IS_LINUX 1) 10 | SET(IS_SUNOS 0) 11 | ELSEIF( CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" ) 12 | SET(IS_FREEBSD 1) 13 | SET(IS_LINUX 0) 14 | SET(IS_SUNOS 0) 15 | ELSEIF( CMAKE_SYSTEM_NAME STREQUAL "SunOS" ) 16 | SET(IS_FREEBSD 0) 17 | SET(IS_LINUX 0) 18 | SET(IS_SUNOS 1) 19 | ENDIF() 20 | 21 | OPTION(BUILD_STATIC_LIBS "Build the static library" OFF) 22 | OPTION(BUILD_SHARED_LIBS "Build the shared library" ON) 23 | 24 | CONFIGURE_FILE(headers/conf.h.in ${CMAKE_CURRENT_BINARY_DIR}/headers/conf.h) 25 | 26 | # Compiler configuration 27 | INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/headers/ ${CMAKE_CURRENT_SOURCE_DIR}/headers/) 28 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 29 | ADD_DEFINITIONS(-Wall -Wextra) 30 | 31 | IF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 32 | SET(CMAKE_INSTALL_PREFIX "/usr") 33 | ENDIF() 34 | 35 | # Install directories 36 | SET(HEADER_DIR "include/libsocket") 37 | SET(LIB_DIR "lib") 38 | 39 | ADD_SUBDIRECTORY(C/) 40 | ADD_SUBDIRECTORY(headers/) 41 | 42 | IF( NOT IS_SUNOS ) 43 | ADD_SUBDIRECTORY(C++/) 44 | ADD_DEPENDENCIES(socket++ socket) 45 | 46 | ENDIF() 47 | 48 | IF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") 49 | SET(CPACK_BINARY_DEB "ON") 50 | SET(CPACK_BINARY_RPM "OFF") 51 | SET(CPACK_BINARY_STGZ "OFF") 52 | SET(CPACK_BINARY_TBZ2 "OFF") 53 | SET(CPACK_BINARY_TGZ "OFF") 54 | SET(CPACK_BINARY_TZ "OFF") 55 | 56 | SET(CPACK_PACKAGE_NAME "libsocket") 57 | SET(CPACK_PACKAGE_VERSION "2.4.0") 58 | SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64") 59 | SET(CPACK_DEBIAN_PACKAGE_DEPENDS "") 60 | SET(CPACK_PACKAGE_CONTACT "Lewin Bormann ") 61 | SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The ultimate socket abstraction library for C and C++.") 62 | 63 | # List executables 64 | INCLUDE(CPack) 65 | ENDIF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") 66 | 67 | set(INSTALL_LIB_DIR lib CACHE PATH "Installation directory for libraries") 68 | set(INSTALL_BIN_DIR bin CACHE PATH "Installation directory for executables") 69 | set(INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header files") 70 | set(DEF_INSTALL_CMAKE_DIR lib/CMake/libsocket) 71 | 72 | foreach(p LIB BIN INCLUDE CMAKE) 73 | set(var INSTALL_${p}_DIR) 74 | if(NOT IS_ABSOLUTE "${${var}}") 75 | set(${var} "${CMAKE_INSTALL_PREFIX}/${${var}}") 76 | endif() 77 | endforeach() 78 | 79 | export(TARGETS socket++ socket_int 80 | FILE "${PROJECT_BINARY_DIR}/libsocketTargets.cmake") 81 | 82 | export(PACKAGE libsocket) 83 | 84 | file(RELATIVE_PATH REL_INCLUDE_DIR "${INSTALL_CMAKE_DIR}" 85 | "${INSTALL_INCLUDE_DIR}") 86 | 87 | set(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/headers") 88 | 89 | configure_file(libsocketConfig.cmake.in 90 | "${PROJECT_BINARY_DIR}/libsocketConfig.cmake" @ONLY) 91 | 92 | configure_file(libsocketConfigVersion.cmake.in 93 | "${PROJECT_BINARY_DIR}/libsocketConfigVersion.cmake" @ONLY) 94 | 95 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Lewin Bormann (lbo) 2 | Andres Erbsen 3 | Markus Elfring (elfring) 4 | BRMateus2 5 | Austin Deric 6 | bruce 7 | Jett 8 | novadan 9 | booto 10 | offa 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | /* 2 | This is a 2-clause BSD license, derived from that used by FreeBSD. It allows you to use 3 | the source code and binaries of libsocket as long as you include this copyright notice in 4 | the files you get from libsocket in your source tree (this notice is already in this files). 5 | 6 | This enables you to include the library (statically or dynamically linked, in binary or source form) 7 | in any kind of software, whether proprietary or open, commercial or free. 8 | */ 9 | /* 10 | The committers of the libsocket project, all rights reserved 11 | (c) 2012 and following, dermesser 12 | 13 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 14 | following conditions are met: 15 | 16 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following 17 | disclaimer. 18 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 19 | disclaimer in the documentation and/or other materials provided with the distribution. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 22 | NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 23 | EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | 29 | */ 30 | -------------------------------------------------------------------------------- /doc/libsocket++/classes.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dermesser/libsocket/6214af728874b98055eefed293274540d98f6568/doc/libsocket++/classes.dia -------------------------------------------------------------------------------- /doc/libsocket++/classes.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | socket 10 | 11 | 12 | 13 | inet_socket 14 | 15 | 16 | 17 | inet_stream_server 18 | 19 | 20 | 21 | 22 | 23 | stream_client_socket 24 | 25 | 26 | 27 | dgram_client_socket 28 | 29 | 30 | 31 | unix_socket 32 | 33 | 34 | 35 | 36 | 37 | 38 | inet_stream 39 | 40 | 41 | 42 | 43 | 44 | inet_dgram 45 | 46 | 47 | 48 | 49 | inet_dgram_server 50 | 51 | 52 | 53 | 54 | inet_dgram_client 55 | 56 | 57 | 58 | 59 | 60 | unix_stream_server 61 | 62 | 63 | 64 | 65 | unix_stream_client 66 | 67 | 68 | 69 | 70 | 71 | unix_dgram 72 | 73 | 74 | 75 | 76 | unix_dgram_server 77 | 78 | 79 | 80 | 81 | unix_dgram_client 82 | 83 | 84 | 85 | Green classes are the only classes which you may instantiate. 86 | 87 | It makes no sense to instantiate a white class 88 | -------------------------------------------------------------------------------- /doxymain.dox: -------------------------------------------------------------------------------- 1 | /** 2 | @mainpage The libsocket documentation 3 | 4 | This documentation is targeted at people who want to gain deeper insight into the libsocket source code. 5 | Normal library users should use the documentation provided in the doc/libsocket and doc/libsocket++ directories! 6 | 7 | This is the documentation for the C and C++ library libsocket. libsocket is intended to simplify the use of internet and 8 | UNIX sockets. Information about how to build libsocket are placed here, and this page 9 | tells you how to use libsocket in your applications. 10 | 11 | @section libsocket libsocket for C 12 | 13 | To get started with *libsocket for C*, take a look at [the hand-crafted documentation](https://github.com/dermesser/libsocket/blob/master/doc/libsocket/DOCUMENTATION.mkd). 14 | 15 | Detailed documentation is available here: libinetsocket; libunixsocket. 17 | 18 | @section libsocketpp libsocket for C++ 19 | 20 | libsocket++ should also be easy to understand but it has a quite sophisticated class hierarchy. 21 | 22 | libsocket++ consists of many C++ classes. Only the following are intended for use in external applications: 23 | 24 | - inet_stream, inet_stream_server (TCP/IP client and server) 25 | - inet_dgram_client, inet_dgram_server (UDP/IP client [unbound] and server [bound]) 26 | - unix_stream_client, unix_stream_server (UNIX domain; STREAM client and server) 27 | - unix_dgram_client, unix_stream_client (UNIX domain; DGRAM unbound and bound sockets) 28 | - selectset, epollset 29 | 30 | If a function fails, it throws a `socket_exception` object containing the error. Look here 31 | for detailed information. *Therefore it's important to put libsocket++ operations inside `try {...} catch () {...}` blocks*. 32 | 33 | Libsocket++ uses C++11 to delete the copy constructors of the socket classes. This enables the destructor to safely 34 | close the socket; to pass a socket to other functions use *call-by-reference*, *call-by-pointer* or `std::move` and an rvalue-accepting function type: 35 | 36 | @code{.cpp} 37 | 38 | void f(xyzsocket&); 39 | void f(xyzsocket*); 40 | 41 | @endcode 42 | 43 | Detailed documentation can be found in this doxygen documentation; easier documentation is available [here](https://github.com/dermesser/libsocket/blob/master/doc/libsocket%2B%2B/DOCUMENTATION%2B%2B.mkd) 44 | 45 | */ 46 | 47 | /************************************** BUILDING **********************************************/ 48 | 49 | /** 50 | @page building Building libsocket 51 | 52 | It should be rather simple to build and install libsocket. 53 | 54 | @section targets Targets 55 | 56 | - all (default): Build both shared objects (libsocket.so, libsocket++.so) 57 | - libsocket: Build only libsocket 58 | - libsocketpp: Build only libsocket++ 59 | - install: Install shared objects and header files 60 | - install-headers: Install headers to (default) `/usr/include/libsocket/` 61 | - clean: Remove object files and shared libraries from source tree 62 | - deinstall: Remove all previously installed files (libraries, header files) 63 | 64 | @section Customization 65 | 66 | You may specify variables when invoking make: `$ make VARIABLE_DECLARATIONS TARGET` 67 | 68 | Predefined vars are: 69 | 70 | LIBPATH=/usr/lib 71 | HEADERPATH=/usr/include/libsocket 72 | CC=gcc 73 | CPP=g++ 74 | CFLAGS= 75 | 76 | If you want to have errors on STDERR from libsocket, simply say `$ make CFLAGS=-DVERBOSE`. If you want to 77 | install the shared libraries to `/usr/local/lib`, use `$ make LIBPATH=/usr/local/lib`. 78 | 79 | */ 80 | 81 | /************************************ USAGE ************************************/ 82 | 83 | /** 84 | @page usage Usage 85 | 86 | As libsocket is built as shared library, it's not really hard to use. 87 | 88 | @section headers Including the header files 89 | 90 | The header files are placed by default to `/usr/include/libsocket` (you may want to change that, especially on BSD). This directory 91 | should be contained in your compiler's include path, so just say (if you want to build an application using UNIX client stream sockets): 92 | 93 | # include 94 | 95 | The classes are contained in these header files: 96 | 97 | CLASS HEADER FILE 98 | ---------------------------------------------------- 99 | inet_stream inetclientstream.hpp 100 | inet_stream_server inetserverstream.hpp 101 | inet_dgram_client inetclientdgram.hpp 102 | inet_dgram_server inetserverdgram.hpp 103 | 104 | unix_dgram_client unixclientdgram.hpp 105 | unix_dgram_server unixserverdgram.hpp 106 | unix_stream_client unixclientstream.hpp 107 | unix_stream_server unixserverstream.hpp 108 | 109 | selectset select.hpp 110 | epollset epoll.hpp 111 | 112 | [libinetsocket] libinetsocket.h 113 | [libunixsocket] libunixsocket.h 114 | 115 | @section linkage Linking your apps with libsocket 116 | 117 | If you let the Makefile place the shared object to a default library path like `/usr/lib`, `/lib`, `/usr/local/lib`, you need to 118 | link your programs with the following switches: 119 | 120 | - For libsocket: `$CC -lsocket ...` 121 | - For libsocket++: `$CXX -lsocket++ ...` 122 | */ 123 | -------------------------------------------------------------------------------- /examples++/README.md: -------------------------------------------------------------------------------- 1 | # `examples++` 2 | 3 | Find some examples on how to use libsocket++ here. 4 | 5 | Some of them are unnecessarily complicated. It is best to take them as starting 6 | point to your own implementation. Have fun! 7 | -------------------------------------------------------------------------------- /examples++/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | g++ -lsocket++ -o dgram_over_stream dgram_over_stream.cpp 4 | g++ -lsocket++ -o framing framing.cpp 5 | g++ -lsocket++ -o unix_dgram_syslogclient unix_dgram_syslogclient.cpp 6 | 7 | -------------------------------------------------------------------------------- /examples++/dgram_over_stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | /* 15 | * This example demonstrates the use of the dgram_over_stream class. As you can 16 | * read in that classes documentation, it simplifies sending discrete packets of 17 | * data over a stream connection. This is achieved by framing; concretely, the 18 | * length of a packet is sent first, so the receiver knows how many bytes to 19 | * expect. 20 | * 21 | * Usage: 22 | * ./dgram_over_stream -c # client 23 | * ./dgram_over_stream -s # server 24 | */ 25 | 26 | using std::string; 27 | 28 | static const string HOST = "localhost"; 29 | static const string PORT = "4445"; 30 | 31 | void run_client(void); 32 | void run_string_client(void); 33 | void run_vec_client(void); 34 | void run_server(void); 35 | 36 | enum MODE { 37 | MODE_CLIENT, 38 | MODE_SERVER, 39 | }; 40 | 41 | MODE get_mode(char** argv) { 42 | if (string(argv[1]) == "-c") { 43 | return MODE_CLIENT; 44 | } else if (string(argv[1]) == "-s") { 45 | return MODE_SERVER; 46 | } else { 47 | perror("Bad command line; please use either -s or -c"); 48 | exit(1); 49 | } 50 | } 51 | 52 | int main(int argc, char** argv) { 53 | assert(argc > 1); 54 | 55 | MODE mode = get_mode(argv); 56 | 57 | try { 58 | if (mode == MODE_CLIENT) { 59 | run_client(); 60 | run_string_client(); 61 | run_vec_client(); 62 | } else if (mode == MODE_SERVER) { 63 | run_server(); 64 | } 65 | } catch (libsocket::socket_exception e) { 66 | std::cerr << e.mesg << std::endl; 67 | } 68 | 69 | return 0; 70 | } 71 | 72 | void run_client(void) { 73 | static const size_t bufsize = 1024; 74 | char buf[bufsize]; 75 | memset(buf, 0, bufsize); 76 | 77 | libsocket::inet_stream client(HOST, PORT, LIBSOCKET_IPv4); 78 | libsocket::dgram_over_stream dgram_cl(std::move(client)); 79 | 80 | dgram_cl.sndmsg("Hello", 5); 81 | std::cout << "Client received " << dgram_cl.rcvmsg(buf, bufsize) 82 | << " bytes.\n"; 83 | std::cout << buf << std::endl; 84 | 85 | return; 86 | } 87 | 88 | void run_string_client(void) { 89 | libsocket::inet_stream client(HOST, PORT, LIBSOCKET_IPv4); 90 | libsocket::dgram_over_stream dgram_cl(std::move(client)); 91 | 92 | std::string recvbuf(0, 'a'); 93 | recvbuf.resize(3); 94 | 95 | dgram_cl.sndmsg(std::string("Hello")); 96 | std::cout << "Client received " << dgram_cl.rcvmsg(&recvbuf) 97 | << " bytes into std::string.\n"; 98 | std::cout << recvbuf << std::endl; 99 | 100 | return; 101 | } 102 | 103 | void run_vec_client(void) { 104 | libsocket::inet_stream client(HOST, PORT, LIBSOCKET_IPv4); 105 | libsocket::dgram_over_stream dgram_cl(std::move(client)); 106 | 107 | std::vector recvbuf; 108 | recvbuf.resize(15); 109 | 110 | dgram_cl.sndmsg(std::string("Hello")); 111 | std::cout << "Client received " << dgram_cl.rcvmsg(&recvbuf) 112 | << " bytes into std::vec.\n"; 113 | 114 | std::for_each(recvbuf.begin(), recvbuf.end(), 115 | [](uint8_t b) { std::cout << static_cast(b); }); 116 | std::cout << std::endl; 117 | 118 | return; 119 | } 120 | 121 | void run_server(void) { 122 | static const size_t bufsize = 1024; 123 | char buf[bufsize]; 124 | memset(buf, 0, bufsize); 125 | 126 | libsocket::inet_stream_server srv(HOST, PORT, LIBSOCKET_IPv4); 127 | 128 | while (true) { 129 | libsocket::inet_stream* client = srv.accept(1); 130 | libsocket::dgram_over_stream dgram_cl(std::move(*client)); 131 | ssize_t len = 0; 132 | 133 | std::cout << "Server received " << (len = dgram_cl.rcvmsg(buf, bufsize)) 134 | << " bytes.\n"; 135 | std::cout << buf << std::endl; 136 | dgram_cl.sndmsg("Hello back", 10); 137 | 138 | memset(buf, 0, len); 139 | } 140 | 141 | return; 142 | } 143 | -------------------------------------------------------------------------------- /examples++/echo/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | g++ -lsocket++ -o conn echo_client_conn.cpp 4 | g++ -lsocket++ -o sndto echo_client_sndto.cpp 5 | g++ -lsocket++ -o srv echo_server.cpp 6 | -------------------------------------------------------------------------------- /examples++/echo/echo_client_conn.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../../headers/exception.hpp" 4 | #include "../../headers/inetclientdgram.hpp" 5 | 6 | /* 7 | * Sends and receives messages to/from the echo_server via connected UDP sockets 8 | */ 9 | 10 | int main(void) { 11 | using std::string; 12 | 13 | string host = "localhost"; 14 | string port = "1234"; 15 | 16 | string answer; 17 | 18 | answer.resize(32); 19 | 20 | libsocket::inet_dgram_client sock(LIBSOCKET_IPv4); 21 | 22 | try { 23 | std::cout << sock.gethost(); 24 | } catch (const libsocket::socket_exception& exc) { 25 | std::cerr << exc.mesg; 26 | } 27 | 28 | try { 29 | for (int i = 0; i < 20; i++) { 30 | sock.connect(host, port); 31 | 32 | sock << "Hello, server"; 33 | 34 | sock >> answer; 35 | 36 | std::cout << "Answer from server: " << answer << std::endl; 37 | 38 | sock.deconnect(); 39 | } 40 | } catch (const libsocket::socket_exception& exc) { 41 | std::cerr << exc.mesg; 42 | } 43 | 44 | sock.destroy(); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /examples++/echo/echo_client_sndto.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../../headers/exception.hpp" 5 | #include "../../headers/inetclientdgram.hpp" 6 | 7 | /* 8 | * Sends and receives messages using the sndto() and rcvfrom functions. 9 | */ 10 | 11 | int main(void) { 12 | using std::string; 13 | 14 | string host = "localhost"; 15 | string port = "1234"; 16 | 17 | string from1; 18 | string from2; 19 | 20 | from1.resize(64); 21 | from2.resize(64); 22 | 23 | string text = "Hello, Server!"; 24 | string buf; 25 | 26 | buf.resize(32); 27 | 28 | libsocket::inet_dgram_client sock(LIBSOCKET_IPv4); 29 | 30 | try { 31 | for (int i = 0; i < 20; i++) { 32 | sock.sndto(text, host, port); 33 | 34 | sock.rcvfrom(buf, from1, from2); 35 | 36 | std::cout << "Answer from " << from1 << ":" << from2 << " - " << buf 37 | << " - " << buf.size() << std::endl; 38 | 39 | std::cout.flush(); 40 | } 41 | } catch (const libsocket::socket_exception& exc) { 42 | std::cerr << exc.mesg; 43 | } 44 | 45 | sock.destroy(); 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /examples++/echo/echo_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../../headers/exception.hpp" 4 | #include "../../headers/inetserverdgram.hpp" 5 | 6 | // Server for echo_client_*.cpp 7 | // Simply receives a datagram message and sends back an answer. 8 | 9 | int main(void) { 10 | using std::string; 11 | 12 | string host = "localhost"; 13 | string port = "1234"; 14 | 15 | string answer("Hello back from the server!"); 16 | string from; 17 | string fromport; 18 | string buf; 19 | 20 | buf.resize(32); 21 | 22 | try { 23 | libsocket::inet_dgram_server srv(host, port, LIBSOCKET_IPv4); 24 | 25 | for (;;) { 26 | srv.rcvfrom(buf, from, fromport); 27 | 28 | std::cout << "Datagram from " << from << ":" << fromport << " " 29 | << buf << std::endl; 30 | 31 | srv.sndto(answer, from, fromport); 32 | } 33 | 34 | // libsocket::inet_dgram_server also has a destructor doing this for 35 | // us, so we are doing explicitly and can reuse the socket. 36 | srv.destroy(); 37 | } catch (const libsocket::socket_exception& exc) { 38 | std::cerr << exc.mesg; 39 | } 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /examples++/framing.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | int main(void) { 10 | char dest[4]; 11 | memset(dest, 0, 4); 12 | uint32_t number = (1 << 30) + 123; 13 | uint32_t decoded; 14 | 15 | libsocket::encode_uint32(number, dest); 16 | 17 | if (number != (decoded = libsocket::decode_uint32(dest))) { 18 | std::cout << "Failure: " << number << " " << decoded << std::endl; 19 | 20 | for (int i = 0; i < 4; i++) { 21 | printf("%02hhx", dest[i]); 22 | } 23 | printf("\n"); 24 | printf("%x\n", decoded); 25 | } 26 | 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /examples++/http_examples/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | g++ -lsocket++ -o http http.cpp 4 | g++ -lsocket++ -o http_2 http_2.cpp 5 | g++ -lsocket++ -o http_epoll http_epoll.cpp 6 | -------------------------------------------------------------------------------- /examples++/http_examples/http.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../../headers/exception.hpp" 4 | #include "../../headers/inetclientstream.hpp" 5 | 6 | // HTTP client demonstrating the use of stream operators 7 | // on STREAM sockets 8 | 9 | int main(void) { 10 | using std::string; 11 | 12 | using libsocket::inet_stream; 13 | 14 | try { 15 | string host = "spheniscida.de"; 16 | string port = "80"; 17 | string answer; 18 | string request1("GET / HTTP/1.1\n"); 19 | string request2("Host: spheniscida.de\n\n"); 20 | 21 | libsocket::inet_stream sock(host, port, LIBSOCKET_IPv4, 0); 22 | 23 | sock << request1 << request2; 24 | 25 | sock.shutdown(LIBSOCKET_WRITE); 26 | 27 | answer.resize(2000); 28 | 29 | while (answer.size() > 0) { 30 | sock >> answer; 31 | 32 | std::cout << answer; 33 | } 34 | 35 | // sock.destroy(); // socket is also destroyed by the destructor 36 | } catch (const libsocket::socket_exception& exc) { 37 | std::cerr << exc.mesg; 38 | } 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /examples++/http_examples/http_2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../../headers/exception.hpp" 4 | #include "../../headers/inetclientstream.hpp" 5 | 6 | // HTTP client demonstrating the use of snd and rcv on STREAM sockets 7 | 8 | int main(void) { 9 | using std::string; 10 | 11 | string host = "spheniscida.de"; 12 | string port = "80"; 13 | ssize_t len; 14 | string test; 15 | 16 | char* buf = new char[10000]; 17 | 18 | try { 19 | libsocket::inet_stream sock(host.c_str(), port.c_str(), LIBSOCKET_IPv4); 20 | 21 | sock.snd("GET / HTTP/1.0\n\n", 16); 22 | 23 | sock.shutdown(LIBSOCKET_WRITE); 24 | 25 | while (0 != (len = sock.rcv(buf, 10000))) 26 | std::cout << string( 27 | buf, len); // write only as many characters as we read 28 | } catch (const libsocket::socket_exception& exc) { 29 | std::cerr << exc.mesg; 30 | } 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /examples++/http_examples/http_epoll.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../../headers/epoll.hpp" 4 | #include "../../headers/exception.hpp" 5 | #include "../../headers/inetclientstream.hpp" 6 | 7 | // HTTP client demonstrating the use of stream operators 8 | // on STREAM sockets, and additionally how to handle epollsets. 9 | 10 | int main(void) { 11 | using std::string; 12 | 13 | using libsocket::epollset; 14 | using libsocket::inet_stream; 15 | 16 | try { 17 | string host = "spheniscida.de"; 18 | string port = "80"; 19 | string answer; 20 | string request1("GET / HTTP/1.1\n"); 21 | string request2("Host: spheniscida.de\n\n"); 22 | 23 | epollset eset; 24 | inet_stream sock(host, port, LIBSOCKET_IPv4, 0); 25 | 26 | sock << request1 << request2; 27 | 28 | sock.shutdown(LIBSOCKET_WRITE); 29 | 30 | eset.add_fd(sock, LIBSOCKET_READ); 31 | 32 | epollset::ready_socks ready = eset.wait(-1); 33 | 34 | libsocket::inet_stream* ready_sock; 35 | 36 | if (ready.first.size() > 0) 37 | ready_sock = ready.first[0]; 38 | else 39 | throw "No socket has been returned!"; 40 | 41 | answer.resize(2000); 42 | 43 | while (answer.size() > 0) { 44 | *ready_sock >> answer; 45 | 46 | std::cout << answer; 47 | } 48 | 49 | // sock.destroy(); // socket is also destroyed by the destructor 50 | } catch (const libsocket::socket_exception& exc) { 51 | std::cerr << exc.mesg; 52 | } 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /examples++/simple_tcp/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | g++ -lsocket++ -o srv server.cpp 4 | g++ -lsocket++ -o cl client.cpp 5 | -------------------------------------------------------------------------------- /examples++/simple_tcp/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../../headers/exception.hpp" 4 | #include "../../headers/inetclientstream.hpp" 5 | 6 | #include 7 | #include 8 | 9 | /* 10 | * This program connects to the server.cpp binary, listens for a message, 11 | * then sends "Hello back!" to the server, closing the socket afterwards. 12 | */ 13 | 14 | int main(void) { 15 | using std::string; 16 | 17 | using libsocket::inet_stream; 18 | 19 | string host = "::1"; 20 | string port = "1235"; 21 | string answer; 22 | 23 | answer.resize(32); 24 | 25 | try { 26 | libsocket::inet_stream sock(host, port, LIBSOCKET_IPv6); 27 | 28 | sock >> answer; 29 | 30 | std::cout << answer; 31 | 32 | sock << "Hello back!\n"; 33 | 34 | // sock is closed here automatically! 35 | } catch (const libsocket::socket_exception& exc) { 36 | std::cerr << exc.mesg; 37 | } 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /examples++/simple_tcp/server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "../../headers/exception.hpp" 8 | #include "../../headers/inetserverstream.hpp" 9 | #include "../../headers/select.hpp" 10 | #include "../../headers/socket.hpp" 11 | 12 | /* 13 | * This server is a bit more complicated than 14 | * what you will need later. It uses the selectset class 15 | * to demonstrate how to use it. 16 | * When a client connects we first send a message and 17 | * receive the client's answer afterwards. 18 | */ 19 | 20 | int main(void) { 21 | using std::string; 22 | using std::unique_ptr; 23 | 24 | using libsocket::inet_stream; 25 | using libsocket::inet_stream_server; 26 | using libsocket::selectset; 27 | 28 | string host = "::1"; 29 | string port = "1235"; 30 | string answ; 31 | 32 | try { 33 | inet_stream_server srv(host, port, LIBSOCKET_IPv6); 34 | 35 | selectset set1; 36 | set1.add_fd(srv, LIBSOCKET_READ); 37 | 38 | for (;;) { 39 | /********* SELECT PART **********/ 40 | std::cout << "Called select()\n"; 41 | 42 | libsocket::selectset::ready_socks 43 | readypair; // Create pair (libsocket::fd_struct is the return 44 | // type of selectset::wait() 45 | 46 | readypair = set1.wait(); // Wait for a connection and save the pair 47 | // to the var 48 | 49 | inet_stream_server* ready_srv = dynamic_cast( 50 | readypair.first 51 | .back()); // Get the last fd of the LIBSOCKET_READ vector 52 | // (.first) of the pair and cast the socket* to 53 | // inet_stream_server* 54 | 55 | readypair.first.pop_back(); // delete the fd from the pair 56 | 57 | std::cout << "Ready for accepting\n"; 58 | 59 | /*******************************/ 60 | 61 | unique_ptr cl1 = ready_srv->accept2(); 62 | 63 | *cl1 << "Hello\n"; 64 | 65 | answ.resize(100); 66 | 67 | *cl1 >> answ; 68 | 69 | std::cout << answ; 70 | 71 | // cl1 is closed automatically when leaving the scope! 72 | } 73 | 74 | srv.destroy(); 75 | 76 | } catch (const libsocket::socket_exception& exc) { 77 | std::cerr << exc.mesg << std::endl; 78 | } 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /examples++/unix_dgram/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | g++ -lsocket++ -o srv unix_dgram_server.cpp 4 | g++ -lsocket++ -o cl unix_dgram_client.cpp 5 | -------------------------------------------------------------------------------- /examples++/unix_dgram/unix_dgram_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../../headers/exception.hpp" 4 | #include "../../headers/unixclientdgram.hpp" 5 | 6 | // Sends a little log message via DGRAM to the syslogd 7 | 8 | int main(void) { 9 | std::string sock = "/tmp/srvsock"; 10 | std::string logmsg = "Hello, server!"; 11 | std::string answer, peer; 12 | 13 | answer.resize(64); 14 | peer.resize(64); 15 | 16 | try { 17 | libsocket::unix_dgram_client cl("/tmp/clsock"); 18 | 19 | cl.sndto(logmsg, sock); 20 | 21 | cl.rcvfrom(answer, peer); 22 | 23 | std::cout << "[client process] " << answer << " from " << peer 24 | << std::endl; 25 | 26 | cl.destroy(); 27 | 28 | } catch (const libsocket::socket_exception& exc) { 29 | std::cerr << exc.mesg; 30 | } 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /examples++/unix_dgram/unix_dgram_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../../headers/exception.hpp" 4 | #include "../../headers/unixserverdgram.hpp" 5 | 6 | // Sends a little log message via DGRAM to the syslogd 7 | 8 | int main(void) { 9 | std::string req; 10 | std::string client; 11 | 12 | req.resize(64); 13 | client.resize(64); 14 | 15 | try { 16 | libsocket::unix_dgram_server srv("/tmp/srvsock"); 17 | 18 | srv.rcvfrom(req, client); 19 | 20 | std::cout << "[server process] " << req << " from " << client 21 | << std::endl; 22 | 23 | srv.sndto("Hiho, client!", client); 24 | 25 | srv.destroy(); 26 | 27 | } catch (const libsocket::socket_exception& exc) { 28 | std::cerr << exc.mesg; 29 | } 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /examples++/unix_dgram_syslogclient.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../headers/exception.hpp" 4 | #include "../headers/unixclientdgram.hpp" 5 | 6 | // Sends a little log message via DGRAM to the syslogd 7 | 8 | int main(void) { 9 | std::string sock = "/dev/log"; 10 | std::string logmsg = "Hello, syslogd! :)"; 11 | 12 | try { 13 | libsocket::unix_dgram_client logcl; 14 | 15 | logcl.sndto(logmsg, sock); 16 | 17 | logcl.destroy(); 18 | } catch (const libsocket::socket_exception& exc) { 19 | std::cerr << exc.mesg; 20 | } 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /examples++/unix_stream/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | g++ -lsocket++ -o cl unix_client_stream.cpp 4 | g++ -lsocket++ -o srv unix_server_stream.cpp 5 | -------------------------------------------------------------------------------- /examples++/unix_stream/unix_client_stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../../headers/exception.hpp" 5 | #include "../../headers/unixclientstream.hpp" 6 | 7 | // Builds a connection to /tmp/unixsocket and sends/receives data using it. 8 | 9 | int main(void) { 10 | using libsocket::unix_stream_client; 11 | using std::string; 12 | 13 | string path = "/tmp/unixsocket"; 14 | char* answer = new char[128]; 15 | 16 | memset(answer, 0, 128); 17 | 18 | try { 19 | unix_stream_client sock(path); 20 | 21 | sock.snd("Hello World!\n", 13); 22 | sock.rcv(answer, 127); 23 | 24 | std::cout << answer; 25 | } catch (const libsocket::socket_exception& exc) { 26 | std::cerr << exc.mesg; 27 | } 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /examples++/unix_stream/unix_server_stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "../../headers/exception.hpp" 6 | #include "../../headers/unixclientstream.hpp" 7 | #include "../../headers/unixserverstream.hpp" 8 | 9 | using std::unique_ptr; 10 | 11 | // Accepts a connection, prints the received message and responds with another 12 | // message. 13 | 14 | int main(void) { 15 | using libsocket::unix_stream_client; 16 | using libsocket::unix_stream_server; 17 | using std::string; 18 | 19 | string bindpath = "/tmp/unixsocket"; 20 | char* answer = new char[128]; 21 | 22 | memset(answer, 0, 128); 23 | 24 | try { 25 | unix_stream_server srv(bindpath); 26 | 27 | unique_ptr client; 28 | client = srv.accept2(); 29 | 30 | client->rcv(answer, 127); 31 | // Alternatively: 32 | // string xyz; 33 | // xyz.resize(127); 34 | //*client >> xyz; 35 | 36 | std::cout << answer; 37 | 38 | *client << "Hello back from server!\n"; 39 | 40 | } catch (const libsocket::socket_exception& exc) { 41 | std::cerr << exc.mesg; 42 | } 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /examples/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | gcc -lsocket -o http http.c 4 | gcc -lsocket -o get_address_family get_address_family.c 5 | gcc -lsocket -o multicast_listen multicast_listen.c 6 | 7 | -------------------------------------------------------------------------------- /examples/echo/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | gcc -lsocket -o srv echo_dgram_server.c 4 | gcc -lsocket -o cl echo_dgram_client.c 5 | gcc -lsocket -o connect_cl echo_dgram_connect_client.c 6 | 7 | -------------------------------------------------------------------------------- /examples/echo/echo_dgram_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "../../headers/libinetsocket.h" 6 | 7 | /* 8 | * This example is part of libsocket/libinetsocket 9 | * 10 | * It sends a UDP packet containing the message 'abcde' to 11 | * localhost:1234 (usually an echo_dgram_server.c instance) 12 | * 13 | */ 14 | 15 | int main(void) { 16 | int sfd; 17 | char buf[16]; 18 | int ret; 19 | 20 | sfd = create_inet_dgram_socket(LIBSOCKET_IPv4, 0); 21 | 22 | if (sfd < 0) { 23 | perror(0); 24 | exit(1); 25 | } 26 | 27 | ret = sendto_inet_dgram_socket(sfd, "abcde", 5, "localhost", "1234", 0); 28 | 29 | if (ret < 0) { 30 | perror(0); 31 | exit(1); 32 | } 33 | 34 | ret = recvfrom_inet_dgram_socket(sfd, buf, 5, 0, 0, 0, 0, 0, 35 | LIBSOCKET_NUMERIC); 36 | 37 | if (ret < 0) { 38 | perror(0); 39 | exit(1); 40 | } 41 | 42 | ret = write(1, buf, 5); 43 | 44 | if (ret < 0) { 45 | perror(0); 46 | exit(1); 47 | } 48 | 49 | ret = destroy_inet_socket(sfd); 50 | 51 | if (ret < 0) { 52 | perror(0); 53 | exit(1); 54 | } 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /examples/echo/echo_dgram_connect_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "../../headers/libinetsocket.h" 6 | 7 | /* 8 | * This example is part of libsocket/libinetsocket 9 | * It works similar to echo_dgram_client.c, but uses 10 | * connected datagram sockets. 11 | * 12 | */ 13 | 14 | int main(void) { 15 | int sfd, ret; 16 | char buf[16]; 17 | 18 | memset(buf, 0, 16); 19 | 20 | ret = sfd = create_inet_dgram_socket(LIBSOCKET_IPv4, 0); 21 | 22 | if (ret < 0) { 23 | perror(0); 24 | exit(1); 25 | } 26 | 27 | ret = connect_inet_dgram_socket(sfd, "localhost", "1234"); 28 | 29 | if (ret < 0) { 30 | perror(0); 31 | exit(1); 32 | } 33 | 34 | ret = write(sfd, "abcde", 5); 35 | 36 | if (ret < 0) { 37 | perror(0); 38 | exit(1); 39 | } 40 | 41 | // We may use the recvfrom/sendto routines also on connected sockets 42 | ret = recvfrom_inet_dgram_socket(sfd, buf, 16, 0, 0, 0, 0, 0, 0); 43 | 44 | if (ret < 0) { 45 | perror(0); 46 | exit(1); 47 | } 48 | 49 | ret = write(1, buf, 5); 50 | 51 | if (ret < 0) { 52 | perror(0); 53 | exit(1); 54 | } 55 | 56 | ret = destroy_inet_socket(sfd); 57 | 58 | if (ret < 0) { 59 | perror(0); 60 | exit(1); 61 | } 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /examples/echo/echo_dgram_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "../../headers/libinetsocket.h" 6 | 7 | /* 8 | * This example is part of libsocket/libinetsocket 9 | * 10 | */ 11 | 12 | /* 13 | * This example is a little echo server processing infinite requests. 14 | * If it receives a string, it writes the string back to the client and to 15 | * stdout. This server uses UDP and listens on 0.0.0.0:1234. It is used with 16 | * echo_dgram_client.c or echo_dgram_connect_client.c. 17 | */ 18 | 19 | int main(void) { 20 | int sfd, bytes, ret; 21 | char src_host[128], src_service[7], buf[16]; 22 | 23 | src_host[127] = 0; 24 | src_service[6] = 0; 25 | 26 | sfd = create_inet_server_socket("0.0.0.0", "1234", LIBSOCKET_UDP, 27 | LIBSOCKET_IPv4, 0); 28 | 29 | if (-1 == sfd) { 30 | perror("couldn't create server\n"); 31 | exit(1); 32 | } 33 | 34 | printf("Socket up and running\n"); 35 | 36 | while (1) { 37 | memset(buf, 0, 16); 38 | ret = bytes = recvfrom_inet_dgram_socket( 39 | sfd, buf, 15, src_host, 127, src_service, 6, 0, LIBSOCKET_NUMERIC); 40 | 41 | if (ret < 0) { 42 | perror(0); 43 | exit(1); 44 | } 45 | 46 | ret = 47 | sendto_inet_dgram_socket(sfd, buf, bytes, src_host, src_service, 0); 48 | 49 | if (ret < 0) { 50 | perror(0); 51 | exit(1); 52 | } 53 | 54 | printf("Connection from %s port %s: %s (%i)\n", src_host, src_service, 55 | buf, bytes); 56 | printf("Connection processed\n"); 57 | } 58 | 59 | ret = destroy_inet_socket(sfd); 60 | 61 | if (ret < 0) { 62 | perror(0); 63 | exit(1); 64 | } 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /examples/get_address_family.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "../headers/libinetsocket.h" 6 | 7 | /* 8 | * This program shows which address family is available 9 | * for a certain host 10 | * 11 | * Usage: $ get_address_family hostname.domain 12 | * 13 | */ 14 | 15 | int main(int argc, char** argv) { 16 | int af = get_address_family(argv[1]); 17 | 18 | switch (af) { 19 | case LIBSOCKET_IPv4: 20 | printf("Supports IPv4\n"); 21 | break; 22 | case LIBSOCKET_IPv6: 23 | printf("Supports IPv6\n"); 24 | break; 25 | default: 26 | printf("No valid result\n"); 27 | } 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /examples/http.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "../headers/libinetsocket.h" 6 | 7 | /* 8 | * This example is part of libsocket/libinetsocket 9 | * It may be used with the most HTTP servers. 10 | * 11 | * This is a almost complete HTTP client, simply 12 | * writing the data to stdout. There's no more code 13 | * with libsocket! 14 | */ 15 | 16 | int main(void) { 17 | int sfd, bytes, ret; 18 | char request[128], buf[32]; 19 | 20 | buf[31] = 0; 21 | 22 | ret = sfd = create_inet_stream_socket("borgac.net", "80", 23 | LIBSOCKET_IPv4, 0); 24 | 25 | if (ret < 0) { 26 | perror(0); 27 | exit(1); 28 | } 29 | 30 | sprintf(request, "GET / HTTP/1.1\nHost: borgac.net\n\n"); 31 | 32 | ret = write(sfd, request, strlen(request)); 33 | 34 | if (ret < 0) { 35 | perror(0); 36 | exit(1); 37 | } 38 | 39 | ret = shutdown_inet_stream_socket(sfd, LIBSOCKET_WRITE); 40 | 41 | if (ret < 0) { 42 | perror(0); 43 | exit(1); 44 | } 45 | 46 | while (0 < (bytes = read(sfd, buf, 31))) write(1, buf, bytes); 47 | 48 | ret = destroy_inet_socket(sfd); 49 | 50 | if (ret < 0) { 51 | perror(0); 52 | exit(1); 53 | } 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /examples/multicast_listen.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "../headers/libinetsocket.h" 8 | 9 | int main(void) { 10 | int c = 0; 11 | char* buffer = malloc(8192); 12 | 13 | // int sfd = create_multicast_socket("225.1.2.3","1230","eth0"); 14 | int sfd = 15 | create_multicast_socket("239.255.255.250", "1900", 16 | "eno1"); // This group/port is used by UPnP 17 | // devices. Maybe you see something? 18 | // int sfd = create_multicast_socket("ff00::abcd","1900","eth0"); 19 | 20 | ssize_t received = 0; 21 | 22 | if (0 > setsockopt(sfd, IPPROTO_IP, IP_MULTICAST_LOOP, &c, 4)) { 23 | fprintf(stderr, "setsockopt failed."); 24 | free(buffer); 25 | exit(1); 26 | } 27 | 28 | while (0 <= (received = read(sfd, buffer, 8191))) { 29 | write(0, buffer, received); 30 | sendto_inet_dgram_socket(sfd, "Hi back", 7, "239.255.255.250", "1900", 31 | 0); 32 | } 33 | 34 | free(buffer); 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /examples/transmission/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | gcc -lsocket -o srv transmission_server.c 4 | gcc -lsocket -o cl transmission_client.c 5 | 6 | -------------------------------------------------------------------------------- /examples/transmission/transmission_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../../headers/libinetsocket.h" 5 | 6 | /* 7 | * Connect to a transmission_server.c instance 8 | * and send a message 9 | */ 10 | 11 | int main(void) { 12 | int ret; 13 | int sfd; 14 | char* buf = "abcde"; 15 | 16 | ret = sfd = create_inet_stream_socket("::1", "55555", LIBSOCKET_IPv6, 0); 17 | 18 | if (ret < 0) { 19 | perror(0); 20 | exit(1); 21 | } 22 | 23 | ret = write(sfd, buf, 5); 24 | 25 | if (ret < 0) { 26 | perror(0); 27 | exit(1); 28 | } 29 | 30 | ret = destroy_inet_socket(sfd); 31 | 32 | if (ret < 0) { 33 | perror(0); 34 | exit(1); 35 | } 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /examples/transmission/transmission_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../../headers/libinetsocket.h" 5 | 6 | /* 7 | * Accept one (1) connection from a transmission_client 8 | * and print the received message. 9 | */ 10 | 11 | int main(void) { 12 | int cfd, sfd, ret; 13 | char* buf = calloc(16, 1); 14 | 15 | ret = sfd = create_inet_server_socket("::", "55555", LIBSOCKET_TCP, 16 | LIBSOCKET_IPv6, 0); 17 | 18 | if (ret < 0) { 19 | perror(0); 20 | exit(1); 21 | } 22 | 23 | ret = cfd = accept_inet_stream_socket(sfd, 0, 0, 0, 0, 0, 0); 24 | 25 | if (ret < 0) { 26 | perror(0); 27 | exit(1); 28 | } 29 | 30 | ret = read(cfd, buf, 15); 31 | 32 | if (ret < 0) { 33 | perror(0); 34 | exit(1); 35 | } 36 | 37 | printf("%s\n", buf); 38 | 39 | ret = destroy_inet_socket(sfd); 40 | 41 | if (ret < 0) { 42 | perror(0); 43 | exit(1); 44 | } 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /examples/unix_dgram/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | gcc -lsocket -o srv unix_dgram_server.c 4 | gcc -lsocket -o cl unix_dgram_client.c 5 | gcc -lsocket -o connect_cl unix_dgram_connect_client.c 6 | 7 | -------------------------------------------------------------------------------- /examples/unix_dgram/unix_dgram_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "../../headers/libunixsocket.h" 6 | 7 | /* 8 | * This example is part of libsocket/libunixsocket 9 | * It may be used with the other part, unix_dgram_server.c 10 | * It should send the content of the string via a DGRAM UNIX socket 11 | * to a unix_dgram_server listening at /tmp/echosock. 12 | */ 13 | 14 | int main(void) { 15 | int sfd, ret; 16 | char* string = "abcdefghijklmnopqrstuvwxyz"; 17 | char buf[26]; 18 | 19 | ret = sfd = create_unix_dgram_socket("/tmp/client", 0); 20 | 21 | if (ret < 0) { 22 | perror(0); 23 | exit(1); 24 | } 25 | 26 | ret = sendto_unix_dgram_socket(sfd, string, 26, "/tmp/echosock", 0); 27 | 28 | if (ret < 0) { 29 | perror(0); 30 | exit(1); 31 | } 32 | 33 | ret = recvfrom_unix_dgram_socket(sfd, buf, 26, 0, 0, 0); 34 | 35 | if (ret < 0) { 36 | perror(0); 37 | exit(1); 38 | } 39 | 40 | ret = write(1, buf, 26); 41 | 42 | if (ret < 0) { 43 | perror(0); 44 | exit(1); 45 | } 46 | 47 | ret = destroy_unix_socket(sfd); 48 | 49 | if (ret < 0) { 50 | perror(0); 51 | exit(1); 52 | } 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /examples/unix_dgram/unix_dgram_connect_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "../../headers/libunixsocket.h" 6 | 7 | /* 8 | * This example is part of libsocket/libunixsocket 9 | * It may be used with the other part, unix_dgram_server.c 10 | * It should send the content of string via a connected DGRAM UNIX socket 11 | * 12 | */ 13 | 14 | int main(void) { 15 | int sfd, ret; 16 | char* string = "abcdefghijklmnopqrstuvwxyz"; 17 | char buf[26]; 18 | 19 | ret = sfd = create_unix_dgram_socket("/tmp/client", 0); 20 | 21 | if (ret < 0) { 22 | perror(0); 23 | exit(1); 24 | } 25 | 26 | ret = connect_unix_dgram_socket(sfd, "/tmp/echosock"); 27 | 28 | if (ret < 0) { 29 | perror(0); 30 | exit(1); 31 | } 32 | 33 | ret = write(sfd, string, 26); 34 | 35 | if (ret < 0) { 36 | perror(0); 37 | exit(1); 38 | } 39 | 40 | ret = read(sfd, buf, 26); 41 | 42 | if (ret < 0) { 43 | perror(0); 44 | exit(1); 45 | } 46 | 47 | write(1, buf, 26); 48 | 49 | ret = destroy_unix_socket(sfd); 50 | 51 | if (ret < 0) { 52 | perror(0); 53 | exit(1); 54 | } 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /examples/unix_dgram/unix_dgram_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "../../headers/libunixsocket.h" 6 | 7 | /* 8 | * This example is part of libsocket/libunixsocket 9 | * It may be used with the other part, unix_dgram_client.c 10 | * It receives up to 127 bytes from a client and prints it on stdout. 11 | * 12 | */ 13 | 14 | int main(void) { 15 | int sfd, bytes, ret; 16 | char buf[128]; 17 | char from[128]; 18 | 19 | memset(buf, 0, 128); 20 | memset(from, 0, 128); 21 | 22 | ret = sfd = create_unix_server_socket("/tmp/echosock", LIBSOCKET_DGRAM, 0); 23 | 24 | if (ret < 0) { 25 | perror(0); 26 | exit(1); 27 | } 28 | 29 | while (0 < (ret = bytes = recvfrom_unix_dgram_socket( 30 | sfd, buf, 127, from, 127, 31 | 0))) // read() is equivalent to recv_ussocket() 32 | { 33 | if (ret < 0) { 34 | perror(0); 35 | exit(1); 36 | } 37 | 38 | write(1, buf, bytes); 39 | ret = sendto_unix_dgram_socket(sfd, buf, bytes, from, 0); 40 | 41 | if (ret < 0) { 42 | perror(0); 43 | exit(1); 44 | } 45 | } 46 | 47 | ret = destroy_unix_socket(sfd); 48 | 49 | if (ret < 0) { 50 | perror(0); 51 | exit(1); 52 | } 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /examples/unix_stream/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | gcc -lsocket -o srv unix_stream_server.c 4 | gcc -lsocket -o cl unix_stream_client.c 5 | 6 | -------------------------------------------------------------------------------- /examples/unix_stream/unix_stream_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "../../headers/libunixsocket.h" 6 | 7 | /* 8 | * This example is part of libsocket/libunixsocket 9 | * It may be used with the other part, unix_stream_server.c 10 | * This example simply sends a string to the echo server 11 | * and tries to receive the answer and print it. 12 | */ 13 | 14 | int main(void) { 15 | int sfd, bytes = 1, ret; 16 | const char* string = "abcdefghijklmnopqrstuvwxyz"; 17 | char buf[16]; 18 | 19 | memset(buf, 0, sizeof(buf)); 20 | 21 | ret = sfd = create_unix_stream_socket("/tmp/echosock", 0); 22 | 23 | if (ret < 0) { 24 | perror(0); 25 | exit(1); 26 | } 27 | 28 | ret = write(sfd, string, 26); 29 | 30 | if (ret < 0) { 31 | perror(0); 32 | exit(1); 33 | } 34 | 35 | ret = shutdown_unix_stream_socket(sfd, LIBSOCKET_WRITE); // Send EOF 36 | 37 | if (ret < 0) { 38 | perror(0); 39 | exit(1); 40 | } 41 | 42 | while (bytes > 0) { 43 | ret = bytes = read(sfd, buf, 15); 44 | 45 | if (ret < 0) { 46 | perror(0); 47 | exit(1); 48 | } 49 | 50 | write(1, buf, bytes); 51 | } 52 | 53 | ret = destroy_unix_socket(sfd); 54 | 55 | if (ret < 0) { 56 | perror(0); 57 | exit(1); 58 | } 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /examples/unix_stream/unix_stream_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../../headers/libunixsocket.h" 5 | 6 | /* 7 | * This example is part of libsocket/libunixsocket 8 | * It may be used with the other part, unix_stream_client.c 9 | * 10 | * The server accepts a connection, reads 15 bytes and writes them 11 | * first back to the client and then to stdout. 12 | */ 13 | 14 | int main(void) { 15 | int sfd, cfd, bytes, ret; 16 | char buf[16]; 17 | 18 | buf[15] = 0; 19 | 20 | ret = sfd = create_unix_server_socket("/tmp/echosock", LIBSOCKET_STREAM, 0); 21 | 22 | if (ret < 0) { 23 | perror(0); 24 | exit(1); 25 | } 26 | 27 | for (;;) { 28 | ret = cfd = accept_unix_stream_socket(sfd, 0); 29 | 30 | if (ret < 0) { 31 | perror(0); 32 | exit(1); 33 | } 34 | 35 | while (0 < (bytes = read(cfd, buf, 15))) { 36 | write(cfd, buf, bytes); 37 | write(1, buf, bytes); 38 | } 39 | 40 | ret = destroy_unix_socket(cfd); 41 | 42 | if (ret < 0) { 43 | perror(0); 44 | exit(1); 45 | } 46 | } 47 | 48 | ret = destroy_unix_socket(sfd); 49 | 50 | if (ret < 0) { 51 | perror(0); 52 | exit(1); 53 | } 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /headers/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.6) 2 | 3 | SET(headers 4 | ./unixdgram.hpp 5 | ./exception.hpp 6 | ./inetclientdgram.hpp 7 | ./libinetsocket.h 8 | ./unixserverstream.hpp 9 | ./dgramclient.hpp 10 | ./streamclient.hpp 11 | ./inetserverstream.hpp 12 | ./unixclientdgram.hpp 13 | ./socket.hpp 14 | ./inetbase.hpp 15 | ./inetserverdgram.hpp 16 | ./unixclientstream.hpp 17 | ./libunixsocket.h 18 | ./select.hpp 19 | ./inetclientstream.hpp 20 | ./unixbase.hpp 21 | ./unixserverdgram.hpp 22 | ./inetdgram.hpp 23 | ./dgramoverstream.hpp 24 | ./framing.hpp 25 | ) 26 | 27 | IF(IS_LINUX) 28 | SET(headers ${headers} ./epoll.hpp) 29 | ENDIF() 30 | 31 | INSTALL(FILES ${headers} DESTINATION ${HEADER_DIR}) 32 | -------------------------------------------------------------------------------- /headers/conf.h.in: -------------------------------------------------------------------------------- 1 | #define LIBSOCKET_VERSION @VERSION@ 2 | #define LIBSOCKET_LINUX @IS_LINUX@ 3 | #define LIBSOCKET_FREEBSD @IS_FREEBSD@ 4 | #define LIBSOCKET_SUNOS @IS_SUNOS@ 5 | -------------------------------------------------------------------------------- /headers/dgramclient.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_DGRAMCLIENT_H_A6969EEDFC57408B89EA3E965C00E811 2 | #define LIBSOCKET_DGRAMCLIENT_H_A6969EEDFC57408B89EA3E965C00E811 3 | 4 | #include 5 | #include 6 | #include 7 | #include "socket.hpp" 8 | 9 | /** 10 | * @file dgramclient.hpp 11 | * 12 | * Contains the dgram_client_socket base class 13 | * 14 | * 15 | The committers of the libsocket project, all rights reserved 16 | (c) 2012, dermesser 17 | 18 | Redistribution and use in source and binary forms, with or without 19 | modification, are permitted provided that the following conditions are met: 20 | 21 | 1. Redistributions of source code must retain the above copyright notice, 22 | this list of conditions and the following disclaimer. 23 | 2. Redistributions in binary form must reproduce the above copyright notice, 24 | this list of conditions and the following disclaimer in the documentation 25 | and/or other materials provided with the distribution. 26 | 27 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 28 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 29 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 31 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 32 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 33 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 34 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 36 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | 38 | 39 | */ 40 | 41 | namespace libsocket { 42 | using std::string; 43 | 44 | /** 45 | * @addtogroup libsocketplusplus 46 | * @{ 47 | */ 48 | 49 | /** 50 | * @brief Represents a generic "client" datagram socket, i.e. a datagram socket 51 | * which can be connected. 52 | */ 53 | class dgram_client_socket : public virtual socket { 54 | protected: 55 | bool connected; ///< Stores the connection state of the socket so other 56 | ///< functions in this class can check if the socket is 57 | ///< connected. The `connection()` method itself is 58 | ///< implemented in derived classes, e.g. inet_dgram_client 59 | 60 | public: 61 | dgram_client_socket(void); 62 | 63 | friend dgram_client_socket& operator<<(dgram_client_socket& sock, 64 | const char* str); 65 | friend dgram_client_socket& operator<<(dgram_client_socket& sock, 66 | const string& str); 67 | 68 | ssize_t snd(const void* buf, size_t len, int flags = 0); // flags: send() 69 | 70 | // I 71 | friend dgram_client_socket& operator>>(dgram_client_socket& sock, 72 | string& dest); 73 | 74 | ssize_t rcv(void* buf, size_t len, int flags = 0); 75 | 76 | // @deprecated 77 | bool getconn(void) const; 78 | 79 | bool is_connected(void) const; 80 | }; 81 | 82 | /** 83 | * @} 84 | */ 85 | } // namespace libsocket 86 | #endif 87 | -------------------------------------------------------------------------------- /headers/dgramoverstream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_DGRAMOVERSTREAM_H_7854202d13e741e98bb3b084eb3d6bc0 2 | #define LIBSOCKET_DGRAMOVERSTREAM_H_7854202d13e741e98bb3b084eb3d6bc0 3 | 4 | #include "exception.hpp" 5 | #include "framing.hpp" 6 | #include "socket.hpp" 7 | #include "streamclient.hpp" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | /** 17 | * @file dgramoverstream.hpp 18 | * 19 | * Contains a class that can be used as wrapper around stream sockets and 20 | * provides framing. That is, an API allowing applications to send discrete 21 | * messages. 22 | */ 23 | /* 24 | The committers of the libsocket project, all rights reserved 25 | (c) 2016, dermesser 26 | 27 | Redistribution and use in source and binary forms, with or without 28 | modification, are permitted provided that the following conditions are met: 29 | 30 | 1. Redistributions of source code must retain the above copyright notice, 31 | this list of conditions and the following disclaimer. 32 | 2. Redistributions in binary form must reproduce the above copyright notice, 33 | this list of conditions and the following disclaimer in the documentation 34 | and/or other materials provided with the distribution. 35 | 36 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 37 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 38 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 39 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 40 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 41 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 42 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 43 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 44 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 45 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 46 | 47 | */ 48 | 49 | namespace libsocket { 50 | /** 51 | * @brief Wraps a stream socket and provides a message-based API on top of it. 52 | * 53 | * Inner has to implement stream and socket methods; those are: snd(), rcv(), 54 | * setsockopt(). It may not be non-blocking, as EWOULDBLOCK is not handled 55 | * gracefully. 56 | * 57 | * This means that if you use sndmsg() to send a frame, then the entire frame 58 | * will be delivered; and the receiver will (provided it uses a 59 | * dgram_over_stream socket as well) receive only the entire message (not parts 60 | * of it). 61 | * 62 | * The internally used format is relatively simple; it uses NBO (big-endian) 63 | * fixed-size 32bit integers as prefix. The prefix encodes how many bytes are 64 | * coming after it. The maximum supported frame size is 2GiB. Schema: [4* u8, 65 | * *u8] 66 | * 67 | * By default, Nagle's algorithm is disabled on the inner stream. This is 68 | * necessary so that a message frame is sent as soon as it is written to the 69 | * socket. If you send a lot of small messages and can accept smaller delays, 70 | * you can enable it again using enable_nagle(). 71 | * 72 | * THIS CLASS IS NOT THREADSAFE. 73 | * 74 | * AS THE STREAM SOCKET WILL BE CLOSED ON DESTRUCTION, IT IS NOT PERMITTED TO 75 | * USE A dgram_over_stream OUTSIDE THE SCOPE OF THE ORIGINAL SOCKET. 76 | * 77 | * THIS CLASS IS IN BETA STATE: IT HAS NOT BEEN TESTED EXTENSIVELY, BUT IS 78 | * EXPECTED TO WORK. 79 | */ 80 | class dgram_over_stream { 81 | public: 82 | dgram_over_stream(void) = delete; 83 | dgram_over_stream(const dgram_over_stream&) = delete; 84 | dgram_over_stream(stream_client_socket inner); 85 | dgram_over_stream(std::unique_ptr inner); 86 | 87 | void enable_nagle(bool enable) const; 88 | 89 | ssize_t sndmsg(const void* buf, size_t len); 90 | ssize_t rcvmsg(void* dst, size_t len); 91 | 92 | ssize_t sndmsg(const std::string& msg); 93 | ssize_t rcvmsg(std::string* dst); 94 | 95 | ssize_t sndmsg(const std::vector& msg); 96 | ssize_t rcvmsg(std::vector* dst); 97 | 98 | private: 99 | static const size_t RECV_BUF_SIZE = 256; 100 | 101 | // The underlying stream. 102 | std::unique_ptr inner; 103 | char prefix_buffer[FRAMING_PREFIX_LENGTH]; 104 | char RECV_BUF[RECV_BUF_SIZE]; 105 | 106 | ssize_t receive_bytes(size_t); 107 | uint32_t receive_header(void); 108 | }; 109 | } // namespace libsocket 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /headers/doxymeta.dox: -------------------------------------------------------------------------------- 1 | /* 2 | * Group definitions for doxygen. 3 | */ 4 | 5 | /** 6 | * @defgroup libsocketplusplus libsocket++ 7 | * This module contains all classes and functions which are part of libsocket++, i.e. all classes and some friend functions. 8 | * Note: To obtain informations about errors, use `errno`. You may find possible values in the syscall's man pages. 9 | * @brief libsocket++ is the C++ wrapper around libinetsocket/libunixsocket 10 | * 11 | * @defgroup libinetsocket libinetsocket 12 | * This module contains all functions which are part of the C internet socket library. 13 | * Note: To obtain informations about errors, use `errno`. You may find possible values in the syscall's man pages. 14 | * @brief C functions for work with BSD sockets (INET domain) 15 | * 16 | * @defgroup libunixsocket libunixsocket 17 | * This module contains all functions which are part of the C Unix socket library 18 | * Note: To obtain informations about errors, use `errno`. You may find possible values in the syscall's man pages. 19 | * @brief C functions for work with BSD sockets (UNIX domain) 20 | */ 21 | -------------------------------------------------------------------------------- /headers/epoll.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_EPOLL_H_E58EF2DF7057FA0C7A95D6E753414229 2 | #define LIBSOCKET_EPOLL_H_E58EF2DF7057FA0C7A95D6E753414229 3 | 4 | /* 5 | The committers of the libsocket project, all rights reserved 6 | (c) 2014, dermesser 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | 11 | 1. Redistributions of source code must retain the above copyright notice, 12 | this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | */ 29 | 30 | /** 31 | * @file epoll.hpp 32 | * @brief [LINUX-only] epoll API abstraction layer. 33 | * 34 | * This template file contains the epollset class which may be used to access 35 | * the modern epoll API of Linux kernels newer than 2.6. 36 | */ 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | #include 44 | 45 | #include "exception.hpp" 46 | #include "socket.hpp" 47 | 48 | using std::vector; 49 | 50 | namespace libsocket { 51 | /** 52 | * @addtogroup libsocketplusplus 53 | * @{ 54 | */ 55 | 56 | /** 57 | * @brief Class abstracting calls to the `epoll` API of Linux. 58 | * 59 | * Being a template, this class needs to be initialized with a class. The choice 60 | * is easy if you only have one type of socket to run epoll on; however, if you 61 | * have (for example) an `inet_stream` and an `inet_stream_server` socket, you 62 | * will need to use either `socket` or `inet_socket` as type parameter so the 63 | * automatic upcasting works as intended. 64 | * 65 | * Upon return of `wait()`, you'll have to identify the sockets (using the 66 | * address -- this class is practically zero-copy) and cast them back with the 67 | * help of `dynamic_cast`. 68 | */ 69 | template 70 | class epollset { 71 | public: 72 | typedef std::pair, std::vector > 73 | ready_socks; 74 | 75 | epollset(unsigned int maxevents = 128); 76 | epollset(const epollset&) = delete; 77 | epollset(epollset&&); 78 | ~epollset(void); 79 | 80 | void add_fd(SocketT& sock, int method); 81 | void del_fd(const SocketT& sock); 82 | ready_socks wait(int timeout = -1); 83 | 84 | private: 85 | /// maxevents is passed to `epoll_wait`. 86 | unsigned int maxevents; 87 | /// The file descriptor used by the epoll API 88 | int epollfd; 89 | /// Array of structures, filled on the return of `epoll_wait`. 90 | struct epoll_event* events; 91 | }; 92 | 93 | /** 94 | * @} 95 | */ 96 | 97 | /** 98 | * @brief Construct a new epollset 99 | * 100 | * @param maxevs Maximum event number returned by `epoll_wait`. Default is 128. 101 | */ 102 | template 103 | epollset::epollset(unsigned int maxevs) 104 | : maxevents(maxevs), events(new struct epoll_event[maxevs]) { 105 | epollfd = epoll_create1(0); 106 | 107 | if (epollfd < 0) 108 | throw socket_exception( 109 | __FILE__, __LINE__, 110 | string("epoll_create1 failed: ") + strerror(errno)); 111 | } 112 | 113 | /** 114 | * @brief Move constructor for epollsets. 115 | */ 116 | template 117 | epollset::epollset(epollset&& new_epollset) { 118 | maxevents = new_epollset.maxevents; 119 | epollfd = new_epollset.epollfd; 120 | events = new_epollset.events; 121 | 122 | new_epollset.epollfd = -1; 123 | new_epollset.events = nullptr; 124 | } 125 | 126 | template 127 | epollset::~epollset(void) { 128 | close(epollfd); 129 | delete[] events; 130 | } 131 | 132 | /** 133 | * @brief Add a socket to an `epollset`. 134 | * 135 | * @param sock The socket to be added. 136 | * @param method Any combination of `LIBSOCKET_READ` and `LIBSOCKET_WRITE`. 137 | */ 138 | template 139 | void epollset::add_fd(SocketT& sock, int method) { 140 | struct epoll_event new_event; 141 | 142 | new_event.data.ptr = 0; // ptr is the largest field (8 bytes on 64bit) 143 | new_event.events = 0; 144 | 145 | if (method & LIBSOCKET_READ) new_event.events |= EPOLLIN; 146 | if (method & LIBSOCKET_WRITE) new_event.events |= EPOLLOUT; 147 | 148 | new_event.data.ptr = &sock; 149 | 150 | if (0 > epoll_ctl(epollfd, EPOLL_CTL_ADD, sock.getfd(), &new_event)) 151 | throw socket_exception(__FILE__, __LINE__, 152 | string("epoll_ctl failed: ") + strerror(errno)); 153 | } 154 | 155 | /** 156 | * @brief Remove a file descriptor from an epoll set. 157 | * 158 | * @param sock The socket to remove. 159 | */ 160 | template 161 | void epollset::del_fd(const SocketT& sock) { 162 | if (0 > epoll_ctl(epollfd, EPOLL_CTL_DEL, sock.getfd(), nullptr)) 163 | throw socket_exception(__FILE__, __LINE__, 164 | string("epoll_ctl failed: ") + strerror(errno)); 165 | } 166 | 167 | /** 168 | * @brief Wait for an event on any file descriptor. 169 | * 170 | * @param timeout (default: -1) Timeout, in milliseconds, after which to return 171 | * if no event has occurred yet. -1 for indefinite waiting, 0 for non-blocking 172 | * access. 173 | * 174 | * @return A pair of vectors containing pointers to SocketTs: 175 | * (ready_for_reading[],ready_for_writing[]). With `r` being the returned pair, 176 | * access the sockets using statements like `r.first.size() > 0 ? r.first[0] : 177 | * nullptr` or the like. 178 | * 179 | * *Hint*: If you need to know what socket has been returned, maintain a mapping 180 | * from socket pointers to some identification code. Using that mapping, you 181 | * will be able to identify the sockets. 182 | * 183 | * *Hint 2*: It never does any harm to check the length of the returned 184 | * `vector`s; with the included example `http_epoll.cpp`, spurious 185 | * empty-returning epoll calls could be observed. However, it is not clear if 186 | * this is a bug in the libsocket implementation or usual behavior of epoll. 187 | */ 188 | template 189 | typename epollset::ready_socks epollset::wait(int timeout) { 190 | int nfds; 191 | ready_socks ready; 192 | 193 | if (0 > (nfds = epoll_wait(epollfd, events, maxevents, timeout))) 194 | throw socket_exception(__FILE__, __LINE__, 195 | string("epoll_wait failed: ") + strerror(errno)); 196 | 197 | for (int i = 0; i < nfds; i++) { 198 | if (events[i].events & EPOLLIN) 199 | ready.first.push_back(static_cast(events[i].data.ptr)); 200 | if (events[i].events & EPOLLOUT) 201 | ready.second.push_back(static_cast(events[i].data.ptr)); 202 | } 203 | 204 | return ready; 205 | } 206 | 207 | } // namespace libsocket 208 | #endif 209 | -------------------------------------------------------------------------------- /headers/exception.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_EXCEPTION_H_07F57E018FF44ADBB169FA2F685EA87E 2 | #define LIBSOCKET_EXCEPTION_H_07F57E018FF44ADBB169FA2F685EA87E 3 | 4 | #include 5 | 6 | /** 7 | * @file exception.hpp 8 | * 9 | * Contains the libsocket exception class, socket_exception 10 | * 11 | * 12 | */ 13 | /* 14 | The committers of the libsocket project, all rights reserved 15 | (c) 2012, dermesser 16 | 17 | Redistribution and use in source and binary forms, with or without 18 | modification, are permitted provided that the following conditions are met: 19 | 20 | 1. Redistributions of source code must retain the above copyright notice, 21 | this list of conditions and the following disclaimer. 22 | 2. Redistributions in binary form must reproduce the above copyright notice, 23 | this list of conditions and the following disclaimer in the documentation 24 | and/or other materials provided with the distribution. 25 | 26 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 27 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 28 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 29 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 30 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 31 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 32 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 33 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 35 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | 37 | */ 38 | 39 | namespace libsocket { 40 | using std::string; 41 | /** 42 | * @addtogroup libsocketplusplus 43 | * @{ 44 | */ 45 | 46 | /** 47 | * @brief This class is instantiated and thrown when an error occurs. 48 | * If there's an error somewhere in libsocket++, the function in which the error 49 | * occurs /always/ throws a `socket_exception` object showing why the error 50 | * occurred. 51 | */ 52 | struct socket_exception { 53 | int err; //!< This is the value of errno when the error occurred. 54 | string mesg; //!< This is the message, showing file, line and a 55 | //!< description. If your program is verbose, simply print it 56 | //!< to STDERR. It contains 1. why the error occurred 2. in 57 | //!< which file it occurred 3. in which line it occurred. It's 58 | //!< a bit like rsync. A typical message looks like the 59 | //!< following one: "../C++/inetclientstream.cpp:167: 60 | //!< <<(std::string) output: Socket not connected!" 61 | 62 | socket_exception(const string& file, int line, const string& message, 63 | bool show_errno = true); 64 | }; 65 | /** 66 | * @} 67 | */ 68 | } // namespace libsocket 69 | #endif 70 | -------------------------------------------------------------------------------- /headers/framing.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_FRAMING_HPP_5a97931a8115428aac8fd1adf96e4595 2 | #define LIBSOCKET_FRAMING_HPP_5a97931a8115428aac8fd1adf96e4595 3 | 4 | #include 5 | 6 | /** 7 | * @file framing.hpp 8 | * @brief Declarations of framing functions. 9 | */ 10 | /* 11 | The committers of the libsocket project, all rights reserved 12 | (c) 2016, dermesser 13 | 14 | Redistribution and use in source and binary forms, with or without 15 | modification, are permitted provided that the following conditions are met: 16 | 17 | 1. Redistributions of source code must retain the above copyright notice, 18 | this list of conditions and the following disclaimer. 19 | 2. Redistributions in binary form must reproduce the above copyright notice, 20 | this list of conditions and the following disclaimer in the documentation 21 | and/or other materials provided with the distribution. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 24 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 27 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 30 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | */ 35 | 36 | namespace libsocket { 37 | const size_t FRAMING_PREFIX_LENGTH = 4; 38 | 39 | void encode_uint32(uint32_t n, char* dst); 40 | uint32_t decode_uint32(const char* src); 41 | } // namespace libsocket 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /headers/inetbase.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_INETBASE_H_6EDE111E3CDD4B07A94ECF4BD4E353C1 2 | #define LIBSOCKET_INETBASE_H_6EDE111E3CDD4B07A94ECF4BD4E353C1 3 | 4 | #include 5 | #include "libinetsocket.h" 6 | #include "socket.hpp" 7 | /** 8 | * @file inetbase.hpp 9 | * 10 | * Contains the IP socket base class. 11 | * 12 | */ 13 | /* 14 | The committers of the libsocket project, all rights reserved 15 | (c) 2012, dermesser 16 | 17 | Redistribution and use in source and binary forms, with or without 18 | modification, are permitted provided that the following conditions are met: 19 | 20 | 1. Redistributions of source code must retain the above copyright notice, 21 | this list of conditions and the following disclaimer. 22 | 2. Redistributions in binary form must reproduce the above copyright notice, 23 | this list of conditions and the following disclaimer in the documentation 24 | and/or other materials provided with the distribution. 25 | 26 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 27 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 28 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 29 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 30 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 31 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 32 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 33 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 35 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | 37 | */ 38 | 39 | namespace libsocket { 40 | using std::string; 41 | 42 | /** 43 | * @addtogroup libsocketplusplus 44 | * @{ 45 | */ 46 | /** 47 | * @brief Internet-socket base class 48 | * This class provides some fields for all internet sockets, like remote host 49 | * and port and the used protocol version. 50 | */ 51 | 52 | class inet_socket : public virtual socket { 53 | protected: 54 | /// The address we're bound or connected to 55 | string host; 56 | /// The port we're bound or connected to 57 | string port; 58 | /// Which internet protocol version we're using 59 | int proto; 60 | 61 | public: 62 | inet_socket(); 63 | 64 | const string& gethost(void) const; 65 | const string& getport(void) const; 66 | }; 67 | /** 68 | * @} 69 | */ 70 | } // namespace libsocket 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /headers/inetclientdgram.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_INETDGRAMCLIENT_H_1E7B8B3247594112BB2CEB2895E916E4 2 | #define LIBSOCKET_INETDGRAMCLIENT_H_1E7B8B3247594112BB2CEB2895E916E4 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "dgramclient.hpp" 9 | #include "inetdgram.hpp" 10 | 11 | /** 12 | * @file inetclientdgram.hpp 13 | * 14 | * Contains the inet_dgram_client class. 15 | */ 16 | /* 17 | The committers of the libsocket project, all rights reserved 18 | (c) 2012, dermesser 19 | 20 | Redistribution and use in source and binary forms, with or without 21 | modification, are permitted provided that the following conditions are met: 22 | 23 | 1. Redistributions of source code must retain the above copyright notice, 24 | this list of conditions and the following disclaimer. 25 | 2. Redistributions in binary form must reproduce the above copyright notice, 26 | this list of conditions and the following disclaimer in the documentation 27 | and/or other materials provided with the distribution. 28 | 29 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 30 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 31 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 32 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 33 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 34 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 35 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 36 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 38 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 | 40 | */ 41 | namespace libsocket { 42 | using std::string; 43 | 44 | /** 45 | * @addtogroup libsocketplusplus 46 | * @{ 47 | */ 48 | /** 49 | * @brief Using UDP/IP easy as never before. 50 | * Class for connectable datagram sockets in the INET domain. You may connect 51 | * this sockets to permanently associate a peer to which all data is sent and 52 | * from which all data is received when using the functions defined in class 53 | * `dgram_client_socket` 54 | */ 55 | class inet_dgram_client : public inet_dgram, public dgram_client_socket { 56 | public: 57 | // Only create socket 58 | inet_dgram_client(int proto_osi3, int flags = 0); // Flags: socket() 59 | // Create socket and connect it 60 | inet_dgram_client(const char* dsthost, const char* dstport, int proto_osi3, 61 | int flags = 0); // Flags: socket() 62 | inet_dgram_client(const string& dsthost, const string& dstport, 63 | int proto_osi3, int flags = 0); 64 | 65 | // actions 66 | // connect/reconnect 67 | void connect(const char* dsthost, const char* dstport); 68 | void connect(const string& dsthost, const string& dstport); 69 | 70 | void deconnect(void); 71 | 72 | private: 73 | void setup(int proto_osi3, int flags = 0); 74 | void setup(const char* dsthost, const char* dstport, int proto_osi3, 75 | int flags = 0); 76 | void setup(const string& dsthost, const string& dstport, int proto_osi3, 77 | int flags = 0); 78 | }; 79 | /** 80 | * @} 81 | */ 82 | } // namespace libsocket 83 | #endif 84 | -------------------------------------------------------------------------------- /headers/inetclientstream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_INETCLIENTSTREAM_H_64300E32D2CB4AD99D557F79F8D340CA 2 | #define LIBSOCKET_INETCLIENTSTREAM_H_64300E32D2CB4AD99D557F79F8D340CA 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "inetbase.hpp" 9 | #include "streamclient.hpp" 10 | 11 | /** 12 | * @file inetclientstream.hpp 13 | * 14 | * inet_stream is the TCP/IP socket class 15 | */ 16 | /* 17 | The committers of the libsocket project, all rights reserved 18 | (c) 2012, dermesser 19 | 20 | Redistribution and use in source and binary forms, with or without 21 | modification, are permitted provided that the following conditions are met: 22 | 23 | 1. Redistributions of source code must retain the above copyright notice, 24 | this list of conditions and the following disclaimer. 25 | 2. Redistributions in binary form must reproduce the above copyright notice, 26 | this list of conditions and the following disclaimer in the documentation 27 | and/or other materials provided with the distribution. 28 | 29 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 30 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 31 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 32 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 33 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 34 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 35 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 36 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 38 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 | 40 | */ 41 | 42 | namespace libsocket { 43 | using std::string; 44 | 45 | /** 46 | * @addtogroup libsocketplusplus 47 | * @{ 48 | */ 49 | /** 50 | * @brief Provides TCP/IP client sockets. 51 | * This class is the most used socket class in libsocket++. It provides plain 52 | * TCP client sockets which can be used for almost everything. 53 | */ 54 | class inet_stream : public inet_socket, public stream_client_socket { 55 | public: 56 | inet_stream(void); 57 | inet_stream(const char* dsthost, const char* dstport, int proto_osi3, 58 | int flags = 0); // flags: socket() 59 | inet_stream(const string& dsthost, const string& dstport, int proto_osi3, 60 | int flags = 0); 61 | 62 | void connect(const char* dsthost, const char* dstport, int proto_osi3, 63 | int flags = 0); // flags: socket() 64 | void connect(const string& dsthost, const string& dstport, int proto_osi3, 65 | int flags = 0); 66 | 67 | friend class inet_stream_server; ///< `inet_stream_server` is our friend so 68 | ///< he may manipulate private members as 69 | ///< `sfd` when returning an instance 70 | ///< (e.g. at `accept()`) 71 | }; 72 | /** 73 | * @} 74 | */ 75 | } // namespace libsocket 76 | #endif 77 | -------------------------------------------------------------------------------- /headers/inetdgram.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_INETDGRAM_H_DD09F601418D47C8893DB605109E3E03 2 | #define LIBSOCKET_INETDGRAM_H_DD09F601418D47C8893DB605109E3E03 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "inetbase.hpp" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | /** 16 | * @file inetdgram.hpp 17 | * 18 | * Contains the inet_dgram class 19 | */ 20 | /* 21 | The committers of the libsocket project, all rights reserved 22 | (c) 2012, dermesser 23 | 24 | Redistribution and use in source and binary forms, with or without 25 | modification, are permitted provided that the following conditions are met: 26 | 27 | 1. Redistributions of source code must retain the above copyright notice, 28 | this list of conditions and the following disclaimer. 29 | 2. Redistributions in binary form must reproduce the above copyright notice, 30 | this list of conditions and the following disclaimer in the documentation 31 | and/or other materials provided with the distribution. 32 | 33 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 34 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 35 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 36 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 37 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 38 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 39 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 40 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 41 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 42 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 43 | 44 | */ 45 | 46 | namespace libsocket { 47 | using std::string; 48 | 49 | /** 50 | * @addtogroup libsocketplusplus 51 | * @{ 52 | */ 53 | /** 54 | * 55 | * @brief Base class for UDP/IP sockets 56 | * 57 | * This classes provides the Send/Receive functions shared by all classes using 58 | * Internet Datagram sockets. 59 | */ 60 | class inet_dgram : public inet_socket { 61 | public: 62 | // I/O 63 | // O 64 | ssize_t sndto(const void* buf, size_t len, const char* dsthost, 65 | const char* dstport, int sndto_flags = 0); // flags: sendto() 66 | ssize_t sndto(const void* buf, size_t len, const string& dsthost, 67 | const string& dstport, int sndto_flags = 0); 68 | 69 | ssize_t sndto(const string& buf, const string& dsthost, 70 | const string& dstport, int sndto_flags = 0); 71 | 72 | // I 73 | ssize_t rcvfrom(void* buf, size_t len, char* srchost, size_t hostlen, 74 | char* srcport, size_t portlen, int rcvfrom_flags = 0, 75 | bool numeric = false); 76 | ssize_t rcvfrom(void* buf, size_t len, string& srchost, string& srcport, 77 | int rcvfrom_flags = 0, bool numeric = false); 78 | 79 | ssize_t rcvfrom(string& buf, string& srchost, string& srcport, 80 | int rcvfrom_flags = 0, bool numeric = false); 81 | }; 82 | /** 83 | * @} 84 | */ 85 | } // namespace libsocket 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /headers/inetserverdgram.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_INETSERVERDGRAM_H_369D8FFD83DD4A78A5A2E3F12EFD0A60 2 | #define LIBSOCKET_INETSERVERDGRAM_H_369D8FFD83DD4A78A5A2E3F12EFD0A60 3 | 4 | #include "inetbase.hpp" 5 | #include "inetdgram.hpp" 6 | 7 | /** 8 | * @file inetserverdgram.hpp 9 | * 10 | * Contains the class for UDP/IP server. 11 | */ 12 | /* 13 | The committers of the libsocket project, all rights reserved 14 | (c) 2012, dermesser 15 | 16 | Redistribution and use in source and binary forms, with or without 17 | modification, are permitted provided that the following conditions are met: 18 | 19 | 1. Redistributions of source code must retain the above copyright notice, 20 | this list of conditions and the following disclaimer. 21 | 2. Redistributions in binary form must reproduce the above copyright notice, 22 | this list of conditions and the following disclaimer in the documentation 23 | and/or other materials provided with the distribution. 24 | 25 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 26 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 27 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 28 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 29 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 30 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 32 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | 36 | */ 37 | 38 | namespace libsocket { 39 | /** @addtogroup libsocketplusplus 40 | * @{ 41 | */ 42 | /** 43 | * @brief Plain UDP sockets 44 | * 45 | * Although called `..._server`, this class may also be used as client (UDP is 46 | * symmetric). It has some special features, e.g. it's not possible to connect 47 | * it. 48 | */ 49 | class inet_dgram_server : public inet_dgram { 50 | public: 51 | inet_dgram_server(const char* host, const char* port, int proto_osi3, 52 | int flags = 0); 53 | inet_dgram_server(const string& host, const string& port, int proto_osi3, 54 | int flags = 0); 55 | 56 | private: 57 | void setup(const char* host, const char* port, int proto_osi3, 58 | int flags = 0); 59 | void setup(const string& host, const string& port, int proto_osi3, 60 | int flags = 0); 61 | }; 62 | /** 63 | * @} 64 | */ 65 | } // namespace libsocket 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /headers/inetserverstream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_INETSERVERSTREAM_H_D84111E97D5548209F3816859EF080FE 2 | #define LIBSOCKET_INETSERVERSTREAM_H_D84111E97D5548209F3816859EF080FE 3 | 4 | #include "inetbase.hpp" 5 | #include "inetclientstream.hpp" 6 | 7 | #include 8 | 9 | /** 10 | * @file inetserverstream.hpp 11 | * 12 | * Contains the class for TCP/IP servers. 13 | */ 14 | /* 15 | The committers of the libsocket project, all rights reserved 16 | (c) 2012, dermesser 17 | 18 | Redistribution and use in source and binary forms, with or without 19 | modification, are permitted provided that the following conditions are met: 20 | 21 | 1. Redistributions of source code must retain the above copyright notice, 22 | this list of conditions and the following disclaimer. 23 | 2. Redistributions in binary form must reproduce the above copyright notice, 24 | this list of conditions and the following disclaimer in the documentation 25 | and/or other materials provided with the distribution. 26 | 27 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 28 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 29 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 31 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 32 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 33 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 34 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 36 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | 38 | */ 39 | 40 | namespace libsocket { 41 | using std::unique_ptr; 42 | 43 | /** 44 | * @addtogroup libsocketplusplus 45 | * @{ 46 | */ 47 | /** 48 | * @brief TCP server socket (passive TCP socket) 49 | * 50 | * This class acts as TCP server. Once set up you may call `accept()` on it. 51 | * When a client wants to connect, a pointer to an `inet_stream` class is 52 | * returned. It may be used to communicate with the client. 53 | * 54 | * @see inet_stream 55 | */ 56 | class inet_stream_server : public inet_socket { 57 | public: 58 | inet_stream_server(void); 59 | inet_stream_server(const char* bindhost, const char* bindport, 60 | int proto_osi3, int flags = 0); 61 | inet_stream_server(const string& bindhost, const string& bindport, 62 | int proto_osi3, int flags = 0); 63 | 64 | void setup(const char* bindhost, const char* bindport, int proto_osi3, 65 | int flags = 0); 66 | void setup(const string& bindhost, const string& bindport, int proto_osi3, 67 | int flags = 0); 68 | 69 | inet_stream* accept(int numeric = 0, int accept_flags = 0); 70 | unique_ptr accept2(int numeric = 0, int accept_flags = 0); 71 | 72 | const string& getbindhost(void); 73 | const string& getbindport(void); 74 | }; 75 | /** 76 | * @} 77 | */ 78 | } // namespace libsocket 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /headers/libinetsocket.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_LIBINETSOCKET_H_C1A9FFEDF5E94B2FB010A0FAA0E92A2F 2 | #define LIBSOCKET_LIBINETSOCKET_H_C1A9FFEDF5E94B2FB010A0FAA0E92A2F 3 | /** 4 | * @file libinetsocket.h 5 | * 6 | * @brief Contains all functions available in the C libsocket. 7 | * 8 | */ 9 | /* 10 | The committers of the libsocket project, all rights reserved 11 | (c) 2012, dermesser 12 | 13 | Redistribution and use in source and binary forms, with or without 14 | modification, are permitted provided that the following conditions are met: 15 | 16 | 1. Redistributions of source code must retain the above 17 | copyright notice, this list of conditions and the following disclaimer. 18 | 2. Redistributions in binary form must reproduce the above 19 | copyright notice, this list of conditions and the following disclaimer in the 20 | documentation and/or other materials provided with the distribution. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND 23 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 26 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /* Headers (e.g. for flags) */ 35 | #include 36 | #include 37 | 38 | /* Macro definitions */ 39 | 40 | #define LIBSOCKET_TCP 1 41 | #define LIBSOCKET_UDP 2 42 | 43 | #define LIBSOCKET_IPv4 3 44 | #define LIBSOCKET_IPv6 4 45 | 46 | #define LIBSOCKET_BOTH \ 47 | 5 /* let the resolver/library choose (TCP/UDP or IPv4/6) */ 48 | 49 | #define LIBSOCKET_READ 1 50 | #define LIBSOCKET_WRITE 2 51 | 52 | #define LIBSOCKET_NUMERIC 1 53 | 54 | #ifdef __cplusplus 55 | #ifdef MIXED 56 | extern "C" { 57 | #endif 58 | #endif 59 | 60 | extern int create_inet_stream_socket(const char* host, const char* service, 61 | char proto_osi3, int flags); 62 | extern int create_inet_dgram_socket(char proto_osi3, int flags); 63 | extern ssize_t sendto_inet_dgram_socket(int sfd, const void* buf, size_t size, 64 | const char* host, const char* service, 65 | int sendto_flags); 66 | extern ssize_t recvfrom_inet_dgram_socket(int sfd, void* buffer, size_t size, 67 | char* src_host, size_t src_host_len, 68 | char* src_service, 69 | size_t src_service_len, 70 | int recvfrom_flags, int numeric); 71 | extern int connect_inet_dgram_socket(int sfd, const char* host, 72 | const char* service); 73 | extern int destroy_inet_socket(int sfd); 74 | extern int shutdown_inet_stream_socket(int sfd, int method); 75 | extern int create_inet_server_socket(const char* bind_addr, 76 | const char* bind_port, char proto_osi4, 77 | char proto_osi3, int flags); 78 | extern int accept_inet_stream_socket(int sfd, char* src_host, 79 | size_t src_host_len, char* src_service, 80 | size_t src_service_len, int flags, 81 | int accept_flags); 82 | extern int get_address_family(const char* hostname); 83 | 84 | #ifdef __linux__ 85 | extern int create_multicast_socket(const char* group, const char* port, 86 | const char* local); 87 | #endif 88 | 89 | #ifdef __cplusplus 90 | #ifdef MIXED 91 | } 92 | #endif 93 | #endif 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /headers/libunixsocket.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_LIBUNIXSOCKET_H_61CF2FC7034E4AD982DA08144D578572 2 | #define LIBSOCKET_LIBUNIXSOCKET_H_61CF2FC7034E4AD982DA08144D578572 3 | /** 4 | * @file libunixsocket.h 5 | * 6 | * Contains all libunixsocket C functions. 7 | * 8 | The committers of the libsocket project, all rights reserved 9 | (c) 2012, dermesser 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | 14 | 1. Redistributions of source code must retain the above 15 | copyright notice, this list of conditions and the following disclaimer. 16 | 2. Redistributions in binary form must reproduce the above 17 | copyright notice, this list of conditions and the following disclaimer in the 18 | documentation and/or other materials provided with the distribution. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND 21 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 24 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 27 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | */ 32 | 33 | /* Headers (e.g. for flags) */ 34 | #include 35 | #include 36 | 37 | /* Macro definitions */ 38 | 39 | #define LIBSOCKET_STREAM 1 40 | #define LIBSOCKET_DGRAM 2 41 | 42 | #define LIBSOCKET_READ 1 43 | #define LIBSOCKET_WRITE 2 44 | 45 | #ifdef __cplusplus 46 | #ifdef MIXED 47 | extern "C" { 48 | #endif 49 | #endif 50 | 51 | extern int create_unix_stream_socket(const char* path, int flags); 52 | extern int create_unix_dgram_socket(const char* bind_path, int flags); 53 | extern int connect_unix_dgram_socket(int sfd, const char* path); 54 | extern int destroy_unix_socket(int sfd); 55 | extern int shutdown_unix_stream_socket(int sfd, int method); 56 | extern int create_unix_server_socket(const char* path, int socktype, int flags); 57 | extern int accept_unix_stream_socket(int sfd, int flags); 58 | extern ssize_t recvfrom_unix_dgram_socket(int sfd, void* buf, size_t size, 59 | char* from, size_t from_size, 60 | int recvfrom_flags); 61 | extern ssize_t sendto_unix_dgram_socket(int sfd, const void* buf, size_t size, 62 | const char* path, int sendto_flags); 63 | 64 | #ifdef __cplusplus 65 | #ifdef MIXED 66 | } 67 | #endif 68 | #endif 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /headers/select.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_SELECT_H_7F761B91E8A84EB685E898542039D68F 2 | #define LIBSOCKET_SELECT_H_7F761B91E8A84EB685E898542039D68F 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace poll { 17 | #include 18 | } 19 | 20 | #include "exception.hpp" 21 | 22 | /** 23 | * @file select.hpp 24 | * 25 | * @brief Contains the class selectset which provides a neat interface for 26 | * watching several sockets 27 | * 28 | * The class selectset implements a wrapper for the syscall poll() (formerly 29 | * select()) which allows to accept connections on more than one socket or 30 | * communicate with multiple clients without multithreading. 31 | * 32 | * New sockets may be added with add_fd(), accepting a child class of 33 | * libsocket::socket. 34 | * 35 | * When all sockets are added, the poll() call can be triggered by calling 36 | * wait(). This function returns a pair of vectors, the first with the 37 | * sockets ready for reading and the second containing the sockets ready for 38 | * writing. 39 | * 40 | * This is a template class; use the appropriate socket class as template 41 | * argument. If you want to select on several different sockets (e.g. an INET 42 | * server and an INET client), use some superclass and `dynamic_cast` to cast 43 | * the pointers returned by `wait()`. 44 | */ 45 | 46 | /* 47 | The committers of the libsocket project, all rights reserved 48 | (c) 2012, dermesser 49 | 50 | Redistribution and use in source and binary forms, with or without 51 | modification, are permitted provided that the following conditions are met: 52 | 53 | 1. Redistributions of source code must retain the above copyright notice, 54 | this list of conditions and the following disclaimer. 55 | 2. Redistributions in binary form must reproduce the above copyright notice, 56 | this list of conditions and the following disclaimer in the documentation 57 | and/or other materials provided with the distribution. 58 | 59 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 60 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 61 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 62 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 63 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 64 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 65 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 66 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 67 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 68 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 69 | 70 | */ 71 | 72 | #include "socket.hpp" 73 | 74 | namespace libsocket { 75 | /** 76 | * @addtogroup libsocketplusplus 77 | * @{ 78 | */ 79 | /** 80 | * @brief selectset provides a simple abstraction over -- contrary to its name 81 | * -- poll(2). 82 | * 83 | * To watch different sockets for new data to read or a possibility to 84 | * write without using threads, use this class. It is rather simple to use; 85 | * add file descriptors (socket ids) using `add_fd()` specifying whether to 86 | * watch them for reading or writing and then call `wait()`; once there's 87 | * data to be read or written it returns a std::pair with vectors of 88 | * `SocketT*`; the first vector contains sockets ready for reading, the 89 | * second one contains those sockets ready for writing. 90 | * 91 | * If you poll sockets of different types, you need to use a superclass as 92 | * template argument to selectset (usually `socket` or `inet_socket`) and 93 | * then `dynamic_cast` the sockets returned in the ready_socks structure 94 | * (see `examples++/server.cpp` for an (artificial) example). 95 | * 96 | * In order to determine which socket in a ready_socks set belongs to which 97 | * connection/server/etc., you should either use the pointer values of 98 | * submitted sockets or the file descriptors managed by your sockets (via 99 | * `Socket::getfd()`). 100 | */ 101 | template 102 | class selectset { 103 | private: 104 | std::map 105 | fdsockmap; ///< A map containing the relations between the 106 | ///< filedescriptors and the socket objects 107 | 108 | bool set_up; ///< Stores if the class has been initiated 109 | 110 | std::vector pollfd_set; // Set of pollfd structs to poll 111 | 112 | public: 113 | selectset(); 114 | 115 | void add_fd(const SocketT& sock, int method); 116 | 117 | std::pair, std::vector > wait( 118 | long long microsecs = 0); 119 | typedef std::pair, std::vector > 120 | ready_socks; 121 | }; 122 | /** 123 | * @} 124 | */ 125 | 126 | extern int highestfd(const std::vector& v); 127 | 128 | /** 129 | * @brief Constructor. 130 | * 131 | * Initializes the sets. 132 | */ 133 | template 134 | selectset::selectset(void) : set_up(false) {} 135 | 136 | /** 137 | * @brief Add a socket to the internal sets 138 | * 139 | * @param sock Some socket. May be server or client socket. 140 | * @param method `LIBSOCKET_READ`/`LIBSOCKET_WRITE` or an `OR`ed combination 141 | * thereof. Determines if the socket is checked on the possibility to read or to 142 | * write. 143 | * 144 | */ 145 | template 146 | void selectset::add_fd(const SocketT& sock, int method) { 147 | int fd = sock.getfd(); 148 | 149 | if (method == LIBSOCKET_READ) { 150 | poll::pollfd fdinfo{fd, POLLIN, 0}; 151 | pollfd_set.push_back(fdinfo); 152 | fdsockmap[fd] = const_cast(&sock); 153 | set_up = true; 154 | 155 | } else if (method == LIBSOCKET_WRITE) { 156 | poll::pollfd fdinfo{fd, POLLOUT, 0}; 157 | pollfd_set.push_back(fdinfo); 158 | fdsockmap[fd] = const_cast(&sock); 159 | set_up = true; 160 | } else if (method == 161 | (LIBSOCKET_READ | LIBSOCKET_WRITE)) { // don't put the fd in our 162 | // data structures twice. 163 | poll::pollfd fdinfo{fd, (POLLIN | POLLOUT), 0}; 164 | pollfd_set.push_back(fdinfo); 165 | fdsockmap[fd] = const_cast(&sock); 166 | set_up = true; 167 | } 168 | } 169 | 170 | /** 171 | * @brief Waits for a possibility to read or write data to emerge. 172 | * 173 | * @param microsecs A timeout in microseconds (for 5 seconds simply write 5e6, 174 | * for ten seconds 10e6 and so on). 0 for no timeout (possibly infinite waiting) 175 | * 176 | * @returns A pair of vectors of pointers to sockets. Information about the type 177 | * of socket is lost; use `dynamic_cast<>()` and check for `NULL` to re-convert 178 | * it. The first vector contains sockets available for reading, the second one 179 | * those available for writing. 180 | * 181 | * *Hint*: Save pointers to the added objects to be able to compare and 182 | * distinguish them after `wait()`. 183 | */ 184 | template 185 | typename selectset::ready_socks selectset::wait( 186 | long long microsecs) { 187 | int n = 0; 188 | 189 | struct timespec* timeout = NULL; 190 | struct timespec _timeout; 191 | 192 | if (microsecs != 0) { 193 | timeout = &_timeout; 194 | 195 | long long nanosecs = microsecs * 1000; 196 | long long nanopart = nanosecs % 1000000000; 197 | long long secpart = (nanosecs - nanopart) / 1000000000; 198 | 199 | _timeout.tv_sec = secpart; 200 | _timeout.tv_nsec = nanopart; 201 | } 202 | 203 | n = ppoll((poll::pollfd*)pollfd_set.data(), pollfd_set.size(), timeout, 204 | NULL); 205 | 206 | ready_socks rwfds; 207 | 208 | if (n < 0) { 209 | std::string err(strerror(errno)); 210 | 211 | throw socket_exception(__FILE__, __LINE__, 212 | "selectset::wait(): Error at ppoll(): " + err); 213 | 214 | } else if (n == 0) // time is over, no filedescriptor is ready 215 | { 216 | rwfds.first.resize(0); 217 | rwfds.second.resize(0); 218 | 219 | return rwfds; 220 | } 221 | 222 | std::vector::iterator end = pollfd_set.end(); 223 | 224 | for (std::vector::iterator iter = pollfd_set.begin(); 225 | iter != end; ++iter) { 226 | if (iter->revents & POLLIN) rwfds.first.push_back(fdsockmap[iter->fd]); 227 | 228 | if (iter->revents & POLLOUT) 229 | rwfds.second.push_back(fdsockmap[iter->fd]); 230 | } 231 | 232 | return rwfds; 233 | } 234 | 235 | } // namespace libsocket 236 | 237 | #endif 238 | -------------------------------------------------------------------------------- /headers/socket.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_SOCKET_H_CCC0882809A540AAAD842D9AE3DB47BB 2 | #define LIBSOCKET_SOCKET_H_CCC0882809A540AAAD842D9AE3DB47BB 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "exception.hpp" 10 | 11 | /** 12 | * @file socket.hpp 13 | * 14 | * Contains the very base class of libsocket++ 15 | */ 16 | /* 17 | The committers of the libsocket project, all rights reserved 18 | (c) 2012, dermesser 19 | 20 | Redistribution and use in source and binary forms, with or without 21 | modification, are permitted provided that the following conditions are met: 22 | 23 | 1. Redistributions of source code must retain the above copyright notice, 24 | this list of conditions and the following disclaimer. 25 | 2. Redistributions in binary form must reproduce the above copyright notice, 26 | this list of conditions and the following disclaimer in the documentation 27 | and/or other materials provided with the distribution. 28 | 29 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 30 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 31 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 32 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 33 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 34 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 35 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 36 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 38 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 | 40 | */ 41 | 42 | #define LIBSOCKET_TCP 1 43 | #define LIBSOCKET_UDP 2 44 | 45 | #define LIBSOCKET_IPv4 3 46 | #define LIBSOCKET_IPv6 4 47 | 48 | #define LIBSOCKET_BOTH 5 // what fits best (TCP/UDP or IPv4/6) 49 | 50 | #define LIBSOCKET_READ 1 51 | #define LIBSOCKET_WRITE 2 52 | 53 | #define LIBSOCKET_NUMERIC 1 54 | 55 | /** 56 | * @brief Contains libsocket elements 57 | * 58 | * All libsocket classes etc are defined within the namespace "libsocket". 59 | */ 60 | namespace libsocket { 61 | /** 62 | * @addtogroup libsocketplusplus 63 | * @{ 64 | */ 65 | /** 66 | * @brief socket is the base class of every other libsocket++ object. 67 | * 68 | * It provides the most important field: The sfd field holds the file descriptor 69 | * for every socket. 70 | */ 71 | class socket { 72 | protected: 73 | /// sfd is the sockets API file descriptor 74 | int sfd; 75 | bool is_nonblocking; 76 | /// Default is true; if set to false, the file descriptor is not closed when 77 | /// the destructor is called. 78 | bool close_on_destructor; 79 | 80 | public: 81 | socket(void); 82 | socket(const socket&) = delete; 83 | socket(socket&&); 84 | 85 | virtual ~socket(); 86 | 87 | virtual int destroy(void); 88 | 89 | int getfd(void) const; 90 | 91 | int set_sock_opt(int level, int optname, const char* optval, 92 | socklen_t optlen) const; 93 | /// `close_on_destructor` is true by default. If set to false, do not call 94 | /// `close(2)` on the underlying socket in the destructor. 95 | void set_close_on_destructor(bool cod) { close_on_destructor = cod; } 96 | }; 97 | /** 98 | * @} 99 | */ 100 | } // namespace libsocket 101 | #endif 102 | -------------------------------------------------------------------------------- /headers/streamclient.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_STREAMCLIENT_H_4EF38CC5CAD740E6B7A55BCF4C48CCFA 2 | #define LIBSOCKET_STREAMCLIENT_H_4EF38CC5CAD740E6B7A55BCF4C48CCFA 3 | 4 | #include 5 | #include "socket.hpp" 6 | 7 | /** 8 | * @file streamclient.hpp 9 | * 10 | * Contains all functions and data members needed by stream socket classes, both 11 | * UNIX and INET. 12 | */ 13 | /* 14 | The committers of the libsocket project, all rights reserved 15 | (c) 2012, dermesser 16 | 17 | Redistribution and use in source and binary forms, with or without 18 | modification, are permitted provided that the following conditions are met: 19 | 20 | 1. Redistributions of source code must retain the above copyright notice, 21 | this list of conditions and the following disclaimer. 22 | 2. Redistributions in binary form must reproduce the above copyright notice, 23 | this list of conditions and the following disclaimer in the documentation 24 | and/or other materials provided with the distribution. 25 | 26 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 27 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 28 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 29 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 30 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 31 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 32 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 33 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 35 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | 37 | */ 38 | 39 | namespace libsocket { 40 | using std::string; 41 | class dgram_over_stream; 42 | 43 | /** @addtogroup libsocketplusplus 44 | * @{ 45 | */ 46 | /** 47 | * @brief Generic socket for active stream sockets (TCP client sockets, UNIX 48 | * Stream clients) 49 | * 50 | * This class defines the basic i/o operations for all stream-based sockets. 51 | */ 52 | class stream_client_socket : public virtual socket { 53 | protected: 54 | bool shut_rd; ///< If the socket was shut down for reading (-> no reads 55 | ///< anymore) 56 | bool shut_wr; ///< If the socket was shut down for writing (-> no writes 57 | ///< anymore) 58 | 59 | public: 60 | stream_client_socket(); 61 | stream_client_socket(const stream_client_socket&) = delete; 62 | stream_client_socket(stream_client_socket&& other) 63 | : socket(std::move(other)), shut_rd(false), shut_wr(false) {} 64 | 65 | ssize_t snd(const void* buf, size_t len, int flags = 0); // flags: send() 66 | ssize_t rcv(void* buf, size_t len, int flags = 0); // flags: recv() 67 | 68 | friend stream_client_socket& operator<<(stream_client_socket& sock, 69 | const char* str); 70 | friend stream_client_socket& operator<<(stream_client_socket& sock, 71 | const string& str); 72 | friend stream_client_socket& operator>>(stream_client_socket& sock, 73 | string& dest); 74 | friend class dgram_over_stream; 75 | 76 | void shutdown(int method = LIBSOCKET_WRITE); 77 | }; 78 | /** 79 | * @} 80 | */ 81 | } // namespace libsocket 82 | #endif 83 | -------------------------------------------------------------------------------- /headers/unixbase.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_UNIXBASE_H_0B648A3E27324425A6B7B9F7B262E7D1 2 | #define LIBSOCKET_UNIXBASE_H_0B648A3E27324425A6B7B9F7B262E7D1 3 | #include 4 | 5 | #include "socket.hpp" 6 | 7 | #include "libunixsocket.h" 8 | 9 | /** 10 | * @file unixbase.hpp 11 | * 12 | * Contains the base class for all UNIX-related socket classes. 13 | */ 14 | /* 15 | The committers of the libsocket project, all rights reserved 16 | (c) 2012, dermesser 17 | 18 | Redistribution and use in source and binary forms, with or without 19 | modification, are permitted provided that the following conditions are met: 20 | 21 | 1. Redistributions of source code must retain the above copyright notice, 22 | this list of conditions and the following disclaimer. 23 | 2. Redistributions in binary form must reproduce the above copyright notice, 24 | this list of conditions and the following disclaimer in the documentation 25 | and/or other materials provided with the distribution. 26 | 27 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 28 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 29 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 31 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 32 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 33 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 34 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 36 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | 38 | */ 39 | 40 | namespace libsocket { 41 | using std::string; 42 | 43 | /** 44 | * @addtogroup libsocketplusplus 45 | * @{ 46 | */ 47 | /** 48 | * @brief Base class for all UNIX socket classes 49 | * 50 | * This class provides only the data member _path and is used as base class for 51 | * every socket class working with UNIX sockets. 52 | */ 53 | class unix_socket : public virtual socket { 54 | protected: 55 | string _path; //!< The path we're connected (client stream) or bound 56 | //!< (server stream, server datagram) 57 | 58 | public: 59 | unix_socket(); 60 | 61 | string get_path(void); 62 | }; 63 | /** 64 | * @} 65 | */ 66 | } // namespace libsocket 67 | #endif 68 | -------------------------------------------------------------------------------- /headers/unixclientdgram.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_UNIXCLIENTDGRAM_H_1A0CF567F9A946AA80C64654F35DFA9E 2 | #define LIBSOCKET_UNIXCLIENTDGRAM_H_1A0CF567F9A946AA80C64654F35DFA9E 3 | 4 | #include "dgramclient.hpp" 5 | #include "unixdgram.hpp" 6 | 7 | #include 8 | 9 | /** 10 | * @file unixclientdgram.hpp 11 | * 12 | * Contains the class for use of UNIX-domain datagram sockets. 13 | */ 14 | /* 15 | The committers of the libsocket project, all rights reserved 16 | (c) 2012, dermesser 17 | 18 | Redistribution and use in source and binary forms, with or without 19 | modification, are permitted provided that the following conditions are met: 20 | 21 | 1. Redistributions of source code must retain the above copyright notice, 22 | this list of conditions and the following disclaimer. 23 | 2. Redistributions in binary form must reproduce the above copyright notice, 24 | this list of conditions and the following disclaimer in the documentation 25 | and/or other materials provided with the distribution. 26 | 27 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 28 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 29 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 31 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 32 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 33 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 34 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 36 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | 38 | */ 39 | 40 | namespace libsocket { 41 | using std::string; 42 | 43 | /** @addtogroup libsocketplusplus 44 | * @{ 45 | */ 46 | /** 47 | * @brief Class for UNIX datagram sockets 48 | */ 49 | class unix_dgram_client : public unix_dgram, public dgram_client_socket { 50 | public: 51 | unix_dgram_client(int flags = 0); 52 | unix_dgram_client(const char* path, int flags = 0); 53 | unix_dgram_client(const string& path, int flags = 0); 54 | 55 | void setup(const char* path, int flags = 0); 56 | 57 | void connect(const char* path); 58 | void connect(const string& path); 59 | 60 | void deconnect(void); 61 | }; 62 | /** 63 | * @} 64 | */ 65 | } // namespace libsocket 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /headers/unixclientstream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_UNIXCLIENTSTREAM_H_9C64A16FB22D46FC9436989C1752F0CF 2 | #define LIBSOCKET_UNIXCLIENTSTREAM_H_9C64A16FB22D46FC9436989C1752F0CF 3 | 4 | #include 5 | 6 | #include "streamclient.hpp" 7 | #include "unixbase.hpp" 8 | 9 | /** 10 | * @file unixclientstream.hpp 11 | * 12 | * Contains the class for use of UNIX-domain stream sockets as client. 13 | */ 14 | /* 15 | The committers of the libsocket project, all rights reserved 16 | (c) 2012, dermesser 17 | 18 | Redistribution and use in source and binary forms, with or without 19 | modification, are permitted provided that the following conditions are met: 20 | 21 | 1. Redistributions of source code must retain the above copyright notice, 22 | this list of conditions and the following disclaimer. 23 | 2. Redistributions in binary form must reproduce the above copyright notice, 24 | this list of conditions and the following disclaimer in the documentation 25 | and/or other materials provided with the distribution. 26 | 27 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 28 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 29 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 30 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 31 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 32 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 33 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 34 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 36 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | 38 | */ 39 | 40 | namespace libsocket { 41 | using std::string; 42 | 43 | /** @addtogroup libsocketplusplus 44 | * @{ 45 | */ 46 | /** 47 | * @brief Provides an interface for working with UNIX STREAM sockets 48 | */ 49 | class unix_stream_client : public unix_socket, public stream_client_socket { 50 | public: 51 | unix_stream_client(void); 52 | unix_stream_client(const char* path, int socket_flags = 0); 53 | unix_stream_client(const string& path, int socket_flags = 0); 54 | 55 | void connect(const char* path, int socket_flags = 0); 56 | void connect(const string& path, int socket_flags = 0); 57 | 58 | friend class unix_stream_server; ///< unix_stream_server returns pointer to 59 | ///< unix_stream_client objects when 60 | ///< accepting connections. 61 | }; 62 | /** 63 | * @} 64 | */ 65 | } // namespace libsocket 66 | #endif 67 | -------------------------------------------------------------------------------- /headers/unixdgram.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_UNIXDGRAM_H_B1DCD9EE9E7E4B379FD5FCA79EF4B63F 2 | #define LIBSOCKET_UNIXDGRAM_H_B1DCD9EE9E7E4B379FD5FCA79EF4B63F 3 | 4 | #include "unixbase.hpp" 5 | 6 | /** 7 | * @file unixdgram.hpp 8 | * 9 | * All functions necessary for UNIX-domain datagram sockets. 10 | */ 11 | /* 12 | The committers of the libsocket project, all rights reserved 13 | (c) 2012, dermesser 14 | 15 | Redistribution and use in source and binary forms, with or without 16 | modification, are permitted provided that the following conditions are met: 17 | 18 | 1. Redistributions of source code must retain the above copyright notice, 19 | this list of conditions and the following disclaimer. 20 | 2. Redistributions in binary form must reproduce the above copyright notice, 21 | this list of conditions and the following disclaimer in the documentation 22 | and/or other materials provided with the distribution. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | 35 | */ 36 | 37 | namespace libsocket { 38 | /** @addtogroup libsocketplusplus 39 | * @{ 40 | */ 41 | /** 42 | * @brief Generic class for all UNIX datagram (DGRAM) sockets, implementing i/o 43 | * functions. 44 | */ 45 | class unix_dgram : public unix_socket { 46 | public: 47 | ssize_t sndto(const void* buf, size_t length, const char* path, 48 | int sendto_flags = 0); 49 | ssize_t sndto(const void* buf, size_t length, const string& path, 50 | int sendto_flags = 0); 51 | 52 | ssize_t sndto(const string& buf, const string& path, int sendto_flags = 0); 53 | 54 | ssize_t rcvfrom(void* buf, size_t length, char* source, size_t source_len, 55 | int recvfrom_flags = 0); 56 | ssize_t rcvfrom(void* buf, size_t length, string& source, 57 | int recvfrom_flags = 0); 58 | 59 | ssize_t rcvfrom(string& buf, string& source, int recvfrom_flags = 0); 60 | }; 61 | /** 62 | * @} 63 | */ 64 | } // namespace libsocket 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /headers/unixserverdgram.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_UNIXSERVERDGRAM_H_110A6B56F8A4414DAB6BE7B527FDA490 2 | #define LIBSOCKET_UNIXSERVERDGRAM_H_110A6B56F8A4414DAB6BE7B527FDA490 3 | 4 | #include "unixdgram.hpp" 5 | 6 | #include 7 | 8 | /** 9 | * @file unixserverdgram.hpp 10 | * 11 | * Contains the class for bound UNIX-domain datagram sockets. 12 | */ 13 | /* 14 | The committers of the libsocket project, all rights reserved 15 | (c) 2012, dermesser 16 | 17 | Redistribution and use in source and binary forms, with or without 18 | modification, are permitted provided that the following conditions are met: 19 | 20 | 1. Redistributions of source code must retain the above copyright notice, 21 | this list of conditions and the following disclaimer. 22 | 2. Redistributions in binary form must reproduce the above copyright notice, 23 | this list of conditions and the following disclaimer in the documentation 24 | and/or other materials provided with the distribution. 25 | 26 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 27 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 28 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 29 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 30 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 31 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 32 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 33 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 35 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | 37 | */ 38 | 39 | namespace libsocket { 40 | using std::string; 41 | 42 | /** @addtogroup libsocketplusplus 43 | * @{ 44 | */ 45 | /** 46 | * @brief Provides an interface to UNIX-domain datagram sockets. 47 | * 48 | * The difference to unix_dgram_client is that this class cannot be connected to 49 | * another socket. 50 | */ 51 | class unix_dgram_server : public unix_dgram { 52 | private: 53 | bool bound; ///< Shows if the socket is already bound (for setup routines) 54 | 55 | public: 56 | unix_dgram_server(void); 57 | unix_dgram_server(const char* bindpath, int socket_flags = 0); 58 | unix_dgram_server(const string& bindpath, int socket_flags = 0); 59 | 60 | void setup(const char* bindpath, int socket_flags = 0); 61 | void setup(const string& bindpath, int socket_flags = 0); 62 | }; 63 | /** 64 | * @} 65 | */ 66 | } // namespace libsocket 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /headers/unixserverstream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LIBSOCKET_UNIXSERVERSTREAM_H_DBD900942A364273A5E9C89F0096D9AF 2 | #define LIBSOCKET_UNIXSERVERSTREAM_H_DBD900942A364273A5E9C89F0096D9AF 3 | 4 | #include 5 | #include 6 | 7 | #include "unixbase.hpp" 8 | #include "unixclientstream.hpp" 9 | 10 | /** 11 | * @file unixserverstream.hpp 12 | * 13 | * UNIX-domain STREAM server socket class 14 | */ 15 | /* 16 | The committers of the libsocket project, all rights reserved 17 | (c) 2012, dermesser 18 | 19 | Redistribution and use in source and binary forms, with or without 20 | modification, are permitted provided that the following conditions are met: 21 | 22 | 1. Redistributions of source code must retain the above copyright notice, 23 | this list of conditions and the following disclaimer. 24 | 2. Redistributions in binary form must reproduce the above copyright notice, 25 | this list of conditions and the following disclaimer in the documentation 26 | and/or other materials provided with the distribution. 27 | 28 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS” AND ANY 29 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 30 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 32 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 33 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 34 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 35 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 36 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 37 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | 39 | */ 40 | 41 | namespace libsocket { 42 | using std::string; 43 | using std::unique_ptr; 44 | 45 | /** @addtogroup libsocketplusplus 46 | * @{ 47 | */ 48 | /** 49 | * @brief Socket class for UNIX-domain STREAM socket server. 50 | */ 51 | class unix_stream_server : public unix_socket { 52 | public: 53 | unix_stream_server(void); 54 | unix_stream_server(const char* path, int flags = 0); 55 | unix_stream_server(const string& path, int flags = 0); 56 | 57 | void setup(const char* path, int flags = 0); 58 | void setup(const string& path, int flags = 0); 59 | 60 | unix_stream_client* accept(int flags = 0); 61 | unique_ptr accept2(int flags = 0); 62 | }; 63 | /** 64 | * @} 65 | */ 66 | } // namespace libsocket 67 | #endif 68 | -------------------------------------------------------------------------------- /libsocketConfig.cmake.in: -------------------------------------------------------------------------------- 1 | set(libsocket_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@") 2 | 3 | set(libsocket_BINARY_DIR "@PROJECT_BINARY_DIR@") 4 | 5 | include(${libsocket_BINARY_DIR}/libsocketTargets.cmake) 6 | 7 | set(libsocket_LIBRARIES socket++) 8 | -------------------------------------------------------------------------------- /libsocketConfigVersion.cmake.in: -------------------------------------------------------------------------------- 1 | set(PACKAGE_VERSION "@VERSION@") 2 | 3 | # Check whether the requested PACKAGE_FIND_VERSION is compatible 4 | if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") 5 | set(PACKAGE_VERSION_COMPATIBLE FALSE) 6 | else() 7 | set(PACKAGE_VERSION_COMPATIBLE TRUE) 8 | if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") 9 | set(PACKAGE_VERSION_EXACT TRUE) 10 | endif() 11 | endif() 12 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | libsocket 4 | 0.0.0 5 | The libsocket package 6 | 7 | dermesser 8 | 9 | 2-clause BSD 10 | 11 | catkin 12 | 13 | 14 | cmake 15 | 16 | 17 | 18 | --------------------------------------------------------------------------------