NetCpp  v0.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Macros Pages
abstract_socket.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2013 Evidence Srl - www.evidence.eu.com
3  *
4  * Boost Software License - Version 1.0 - August 17th, 2003
5  *
6  * Permission is hereby granted, free of charge, to any person or organization
7  * obtaining a copy of the software and accompanying documentation covered by
8  * this license (the "Software") to use, reproduce, display, distribute,
9  * execute, and transmit the Software, and to prepare derivative works of the
10  * Software, and to permit third-parties to whom the Software is furnished to
11  * do so, all subject to the following:
12  *
13  * The copyright notices in the Software and this entire statement, including
14  * the above license grant, this restriction and the following disclaimer,
15  * must be included in all copies of the Software, in whole or in part, and
16  * all derivative works of the Software, unless such copies or derivative
17  * works are solely in the form of machine-executable object code generated by
18  * a source language processor.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
23  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
24  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
25  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  * DEALINGS IN THE SOFTWARE.
27  */
28 
29 #include "abstract_socket.hpp"
30 
31 namespace net {
32 
33 /**
34  * @brief Receive operation
35  *
36  * This function sendsendsensendsendsendcare of synchronization
37  * with any other asynchronous operations.
38  * Note: it can block the caller, because it calls __receive() which
39  * continues receiving until the given number of bytes have been received.
40  * @param buf Pointer where received data must be put
41  * @param size Size of data to be received
42  * @return Number of bytes actually received
43  * @exception runtime_error in case of too small buffer
44  *
45  * Example of usage:
46  * <code>
47  * std::array<char, 5> buf;
48  * AbstractSocket::receive(net::buffer(b), 3);
49  * </code>
50  */
51 int AbstractSocket::receive (struct __buffer buf, std::size_t size)
52 {
53  int ret;
54  if (buf.size_ == 0 || size > buf.size_){
55  ERROR("Wrong buffer size!");
56  throw std::runtime_error ("Wrong buffer size");
57  }
58  receive_lock_.lock();
59  try {
60  ret = __receive(buf.ptr_, size);
61  } catch (...) {
62  ERROR("Receive error!");
63  }
64 
65  receive_lock_.unlock();
66  return ret;
67 }
68 
69 /**
70  * @brief Send operation
71  *
72  * This function sends data to the socket taking care of synchronization
73  * with any other asynchronous operations.
74  * Note: it can block the caller, because it calls __send() which
75  * continues writing until the given number of bytes have been written.
76  * @param buf Pointer to data to be written
77  * @param size Size of data to be written
78  * @return Number of bytes actually written
79  * @exception runtime_error in case of too small buffer
80  *
81  * Example of usage:
82  * <code>
83  * std::array<char, 5> buf;
84  * AbstractSocket::send(net::buffer(b), 3);
85  * </code>
86  */
87 int AbstractSocket::send (struct __buffer buf, std::size_t size)
88 {
89  int ret;
90  if (buf.size_ == 0 || size > buf.size_){
91  ERROR("Wrong buffer size!");
92  throw std::runtime_error ("Wrong buffer size");
93  }
94  send_lock_.lock();
95  try {
96  ret = __send(buf.ptr_, size);
97  } catch (...) {
98  ERROR("Send error!");
99  }
100 
101  send_lock_.unlock();
102  return ret;
103 
104 }
105 
106 /**
107  * \brief Low-level receive
108  *
109  * This method is private because it is meant to be used through the other receive()
110  * method.
111  * Note: it can block the caller, because it continues receiving until the given
112  * number of bytes have been received.
113  * @param buffer Pointer to the buffer where received bytes must be stored
114  * @param size Number of bytes to be received
115  * @exception runtime_error if the read() returns an error
116  * @return The number of actually received bytes or -1 in case of error
117  */
118 int AbstractSocket::__receive (void* buffer, size_t size)
119 {
120  size_t remaining = size;
121  while (remaining > 0) {
122  ssize_t ret = socket_->read (((char*)buffer)+(size-remaining),
123  remaining);
124  if (ret == 0){
125  // End of file reached
126  DEBUG("End of file reached");
127  break;
128  } else if (ret < 0) {
129  ERROR("Receive error");
130  throw std::runtime_error ("Receive error");
131  return -1;
132  }
133  remaining -= ret;
134  }
135  return (size-remaining);
136 }
137 
138 
139 
140 /**
141  * \brief Low-level send
142  *
143  * This method is private because it is meant to be used through the other
144  * send() method.
145  * Note: it can block the caller, because it continues writing until the
146  * given number of bytes have been written.
147  * @param buffer Pointer to the buffer containing bytes to be written
148  * @param size Number of bytes to be written
149  * @exception runtime_error if the write() returns 0 or an error
150  * @return The number of actually written bytes or -1 in case of error
151  */
152 int AbstractSocket::__send(const void* buffer, size_t size)
153 {
154  size_t remaining = size;
155  while (remaining > 0) {
156  ssize_t ret = socket_->write (((char*)buffer)+(size-remaining), remaining);
157  if (ret == 0){
158  DEBUG("Cannot send any further");
159  // Cannot send more
160  break;
161  } else if (ret < 0) {
162  ERROR("Send error");
163  throw std::runtime_error ("Send error");
164  return -1;
165  }
166  remaining -= ret;
167  }
168  return (size-remaining);
169 }
170 
171 } // net