libsocket
streamclient.cpp
Go to the documentation of this file.
1 /*
2  The committers of the libsocket project, all rights reserved
3  (c) 2012, dermesser <lbo@spheniscida.de>
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 
36 #include <string.h>
37 #include <unistd.h>
38 #include <memory>
39 #include <string>
40 // Inclusion here prevents further inclusion from headers/socket.hpp
41 namespace BERKELEY {
42 #include <sys/socket.h>
43 } // namespace BERKELEY
44 
45 #include <conf.h>
46 #include <libinetsocket.h>
47 #include <exception.hpp>
48 #include <streamclient.hpp>
49 
50 namespace libsocket {
54 stream_client_socket::stream_client_socket() : shut_rd(false), shut_wr(false) {}
55 
68 ssize_t stream_client_socket::rcv(void* buf, size_t len, int flags) {
69  ssize_t recvd;
70 
71  if (shut_rd == true)
72  throw socket_exception(
73  __FILE__, __LINE__,
74  "stream_client_socket::rcv() - Socket has already been shut down!",
75  false);
76 
77  if (sfd == -1)
78  throw socket_exception(
79  __FILE__, __LINE__,
80  "stream_client_socket::rcv() - Socket is not connected!", false);
81 
82  if (buf == NULL || len == 0)
83  throw socket_exception(
84  __FILE__, __LINE__,
85  "stream_client_socket::rcv() - Buffer or length is null!", false);
86 
87  memset(buf, 0, len);
88 
89  if (-1 == (recvd = BERKELEY::recv(sfd, buf, len, flags))) {
90  if (is_nonblocking && errno == EWOULDBLOCK)
91  return -1;
92  else
93  throw socket_exception(
94  __FILE__, __LINE__,
95  "stream_client_socket::rcv() - Error while reading!");
96  }
97 
98  return recvd;
99 }
100 
119  ssize_t read_bytes;
120 
121  if (sock.shut_rd == true)
122  throw socket_exception(__FILE__, __LINE__,
123  "stream_client_socket::operator>>(std::string) "
124  "- Socket has already been shut down!",
125  false);
126 
127  using std::unique_ptr;
128  unique_ptr<char[]> buffer(new char[dest.size()]);
129 
130  memset(buffer.get(), 0, dest.size());
131 
132  if (sock.sfd == -1) {
133  throw socket_exception(__FILE__, __LINE__,
134  ">>(std::string) input: Socket not connected!",
135  false);
136  }
137 
138  if (-1 == (read_bytes = read(sock.sfd, buffer.get(), dest.size()))) {
139  if (sock.is_nonblocking && errno == EWOULDBLOCK) {
140  dest.clear();
141  return sock;
142  } else
143  throw socket_exception(
144  __FILE__, __LINE__,
145  ">>(std::string) input: Error while reading!");
146  }
147 
148  if (read_bytes < static_cast<ssize_t>(dest.size()))
149  dest.resize(read_bytes); // So the client doesn't print content more
150  // than one time and it can check if the
151  // string's length is 0 (end of transmission)
152 
153  dest.assign(buffer.get(), read_bytes);
154 
155  return sock;
156 }
157 
158 // O
159 
175  if (sock.shut_wr == true)
176  throw socket_exception(__FILE__, __LINE__,
177  "stream_client_socket::operator<<(const char*) "
178  "- Socket has already been shut down!",
179  false);
180  if (sock.sfd == -1)
181  throw socket_exception(__FILE__, __LINE__,
182  "<<(const char*) output: Socket not connected!",
183  false);
184  if (str == NULL)
185  throw socket_exception(__FILE__, __LINE__,
186  "<<(const char*) output: Null buffer given!",
187  false);
188 
189  size_t len = strlen(str);
190 
191  if (-1 == write(sock.sfd, str, len))
192  throw socket_exception(__FILE__, __LINE__,
193  "<<(const char*) output: Write failed!");
194 
195  return sock;
196 }
197 
213  const string& str) {
214  if (sock.shut_wr == true)
215  throw socket_exception(__FILE__, __LINE__,
216  "stream_client_socket::operator<<(std::string) "
217  "- Socket has already been shut down!",
218  false);
219  if (sock.sfd == -1)
220  throw socket_exception(__FILE__, __LINE__,
221  "<<(std::string) output: Socket not connected!",
222  false);
223 
224  if (-1 == write(sock.sfd, str.c_str(), str.size()))
225  throw socket_exception(__FILE__, __LINE__,
226  "<<(std::string) output: Write failed!");
227 
228  return sock;
229 }
230 
243 ssize_t stream_client_socket::snd(const void* buf, size_t len, int flags) {
244  ssize_t snd_bytes;
245 
246  if (shut_wr == true)
247  throw socket_exception(
248  __FILE__, __LINE__,
249  "stream_client_socket::snd() - Socket has already been shut down!",
250  false);
251  if (sfd == -1)
252  throw socket_exception(
253  __FILE__, __LINE__,
254  "stream_client_socket::snd() - Socket not connected!", false);
255  if (buf == NULL || len == 0)
256  throw socket_exception(
257  __FILE__, __LINE__,
258  "stream_client_socket::snd() - Buffer or length is null!", false);
259 
260  if (-1 == (snd_bytes = BERKELEY::send(sfd, buf, len, flags))) {
261  if (is_nonblocking && errno == EWOULDBLOCK)
262  return -1;
263  else
264  throw socket_exception(
265  __FILE__, __LINE__,
266  "stream_client_socket::snd() - Error while sending");
267  }
268 
269  return snd_bytes;
270 }
271 
280  int u_method = 0; // unix flags
281 
282  // Already shut down using this method...
283  if ((method & (LIBSOCKET_READ | LIBSOCKET_WRITE)) && (shut_rd == true) &&
284  (shut_wr == true))
285  return;
286  if ((method & LIBSOCKET_READ) && (shut_rd == true)) return;
287  if ((method & LIBSOCKET_WRITE) && (shut_wr == true)) return;
288 
289 #if LIBSOCKET_LINUX || BD_ANDROID
290  using BERKELEY::SHUT_RD;
291  using BERKELEY::SHUT_RDWR;
292  using BERKELEY::SHUT_WR;
293 #endif
294 
295  if (method == (LIBSOCKET_READ | LIBSOCKET_WRITE))
296  u_method = SHUT_RDWR;
297  else if (method == LIBSOCKET_READ)
298  u_method = SHUT_RD;
299  else if (method == LIBSOCKET_WRITE)
300  u_method = SHUT_WR;
301  else // With no valid combination
302  return;
303 
304  if (0 >
305  BERKELEY::shutdown(sfd, u_method)) // It's equal whether we use this or
306  // its brother from libunixsocket
307  {
308  throw socket_exception(
309  __FILE__, __LINE__,
310  "stream_client_socket::shutdown() - Could not shutdown socket");
311  }
312 
313  if (method & LIBSOCKET_READ) shut_rd = true;
314  if (method & LIBSOCKET_WRITE) shut_wr = true;
315 }
316 } // namespace libsocket
Contains libsocket elements.
Definition: dgramclient.hpp:41
This class is instantiated and thrown when an error occurs. If there's an error somewhere in libsocke...
Definition: exception.hpp:52
ssize_t rcv(void *buf, size_t len, int flags=0)
Receive data from socket.
dgram_client_socket & operator>>(dgram_client_socket &sock, string &dest)
Receive data from connected datagram socket.
Definition: dgramclient.cpp:95
stream_client_socket()
Void constructor.
dgram_client_socket & operator<<(dgram_client_socket &sock, const char *str)
Send data to connected peer.
ssize_t snd(const void *buf, size_t len, int flags=0)
Send data to socket.
int sfd
sfd is the sockets API file descriptor
Definition: socket.hpp:74
Generic socket for active stream sockets (TCP client sockets, UNIX Stream clients)
void shutdown(int method=LIBSOCKET_WRITE)
Shut a socket down.
Contains all functions available in the C libsocket.