libsocket  1.5
localsocket.cc
Go to the documentation of this file.
1 /*
2 ** localsocket.cc
3 ** Login : Julien Lemoine <speedblue@happycoders.org>
4 ** Started on Sun May 11 22:19:51 2003 Julien Lemoine
5 ** $Id: localsocket.cc,v 1.9 2004/11/14 19:37:46 speedblue Exp $
6 **
7 ** Copyright (C) 2003,2004 Julien Lemoine
8 ** This program is free software; you can redistribute it and/or modify
9 ** it under the terms of the GNU Lesser General Public License as published by
10 ** the Free Software Foundation; either version 2 of the License, or
11 ** (at your option) any later version.
12 **
13 ** This program is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ** GNU Lesser General Public License for more details.
17 **
18 ** You should have received a copy of the GNU Lesser General Public License
19 ** along with this program; if not, write to the Free Software
20 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22 
23 #include "localsocket.hh"
24 
25 #ifndef LIBSOCKET_WIN
26 
27 #include <sys/types.h>
28 #include <sys/un.h>
29 #include <cstddef>
30 #include "socket.hxx"
31 
32 namespace Network
33 {
34  void LocalSocket::init(const std::string& filename)
35  {
36  _socket = _bind(filename);
37  _filename = filename;
38  }
39 
41  {
42  if (_socket > 0)
43  _close(_socket);
44  _socket = 0;
45  unlink(_filename.c_str());
46  _filename = "";
47  }
48 
49  int LocalSocket::_bind(const std::string& filename)
50  {
51  int s;
52  struct sockaddr_un name;
53  size_t size;
54 
55  s = socket(PF_UNIX, SOCK_DGRAM, 0);
56  if (s < 0)
57  throw NoConnection("Socket error", HERE);
58  name.sun_family = AF_UNIX;
59  strncpy(name.sun_path, filename.c_str(), sizeof (name.sun_path));
60  name.sun_path[sizeof (name.sun_path) - 1] = '\0';
61  size = (offsetof (struct sockaddr_un, sun_path)
62  + strlen (name.sun_path) + 1);
63  if (bind (s, (struct sockaddr *) &name, size) < 0)
64  throw BindError("Bind error", HERE);
65  return s;
66  }
67 
68  void LocalSocket::_write_str(int socket, const std::string& str,
69  const std::string& filename) const
70  {
71  int res = 1;
72  const char *buf = str.c_str();
73  unsigned int count = 0;
74  struct sockaddr_un name;
75 
76  name.sun_family = AF_UNIX;
77  strncpy(name.sun_path, filename.c_str(), sizeof (name.sun_path));
78  name.sun_path[sizeof (name.sun_path) - 1] = '\0';
79 
80  if (socket < 0)
81  throw NoConnection("No Socket", HERE);
82  while (res && count < str.size())
83  {
84  res = sendto(socket, buf + count,
85  str.size() - count, SENDTO_FLAGS,
86  (const struct sockaddr*)&name, sizeof(name));
87  if (res <= 0)
88  throw ConnectionClosed("Connection Closed", HERE);
89  count += res;
90  }
91  }
92 
93  void LocalSocket::_write_str_bin(int socket, const std::string& str,
94  const std::string& filename) const
95  {
96  int res = 1;
97  unsigned int count = 0;
98  struct sockaddr_un name;
99  char buf[str.size() + 2];
100 
101  buf[0] = str.size() / 256;
102  buf[1] = str.size() % 256;
103  memcpy(buf + 2, str.c_str(), str.size());
104  name.sun_family = AF_UNIX;
105  strncpy(name.sun_path, filename.c_str(), sizeof (name.sun_path));
106  name.sun_path[sizeof (name.sun_path) - 1] = DEFAULT_DELIM;
107 
108  if (socket < 0)
109  throw NoConnection("No Socket", HERE);
110  while (res && count < str.size() + 2)
111  {
112  res = sendto(socket, buf + count, str.size() + 2 - count, SENDTO_FLAGS,
113  (const struct sockaddr*)&name, sizeof(name));
114  if (res <= 0)
115  throw ConnectionClosed("Connection Closed", HERE);
116  count += res;
117  }
118  }
119 
120  std::string LocalSocket::_read_line(int socket,
121  std::string& filename)
122  {
123  char chr[MAXPKTSIZE];
124  std::string str = "";
125  int res = 1, i;
126  std::pair<int, int> delim;
127  struct sockaddr_un addr;
128  size_t size;
129  bool end = false;
130 
131  size = sizeof(addr);
132  if (socket < 0)
133  throw NoConnection("No Socket", HERE);
134  if (!_update_buffer(delim, i, str))
135  while (!end)
136  {
137 #ifdef __CYGWIN__
138  res = recvfrom(socket, chr, MAXPKTSIZE, 0,
139  (struct sockaddr*)&addr,
140  (socklen_t*)&size);
141 #else
142  res = recvfrom(socket, chr, MAXPKTSIZE, MSG_TRUNC,
143  (struct sockaddr*)&addr,
144  (socklen_t*)&size);
145 #endif
146  if (res <= 0)
147  throw ConnectionClosed("Connection Closed", HERE);
148  _buffer += std::string(chr, res);
149  if (_update_buffer(delim, i, str))
150  end = true;
151  }
152  filename = std::string(addr.sun_path);
153  _state_timeout = 0;
154  return str;
155  }
156 
157  std::string LocalSocket::_read_line_bin(int socket, unsigned int size)
158  {
159  char chr[MAXPKTSIZE];
160  std::string str = "";
161  int res = 1;
162  bool end = false;
163 
164  if (socket < 0)
165  throw NoConnection("No Socket", HERE);
166  if (_buffer.size() >= 2 && !size)
167  {
168  size = (unsigned char)_buffer[0] * 256 + (unsigned char)_buffer[1];
169  _buffer = _buffer.substr(2, _buffer.size() - 2);
170  }
171  if (size && _buffer.size() >= size)
172  {
173  str = _buffer.substr(0, size);
174  _buffer = _buffer.substr(size, _buffer.size() - size);
175  }
176  else
177  while (!end)
178  {
179  memset(chr, 0, MAXPKTSIZE);
180 #ifdef __CYGWIN__
181  res = recv(socket, chr, MAXPKTSIZE, 0);
182 #else
183  res = recv(socket, chr, MAXPKTSIZE, MSG_TRUNC);
184 #endif
185  if (res <= 0)
186  throw ConnectionClosed("Connection Closed", HERE);
187  // _buffer += all octets received
188  _buffer += std::string(chr, res);
189  if (!size)
190  {
191  // extract size from _buffer and reduce it
192  size = (unsigned char)_buffer[0] * 256 + (unsigned char)_buffer[1];
193  _buffer = _buffer.substr(2, _buffer.size() - 2);
194  }
195  if (_buffer.size() > size - str.size())
196  {
197  str += _buffer.substr(0, size - str.size());
198  _buffer = _buffer.substr(size - str.size(),
199  _buffer.size() - size - str.size());
200  }
201  else
202  {
203  str += _buffer;
204  _buffer = "";
205  }
206  if (str.size() >= size)
207  end = true;
208  }
209  return str;
210  }
211 
212  std::string LocalSocket::_read_line(int socket)
213  {
214  char chr[MAXPKTSIZE];
215  std::string str = "";
216  int res = 1, i;
217  std::pair<int, int> delim;
218  bool end = false;
219 
220  if (socket < 0)
221  throw NoConnection("No Socket", HERE);
222  if (!_update_buffer(delim, i, str))
223  while (!end)
224  {
225  memset(chr, 0, MAXPKTSIZE);
226 #ifdef __CYGWIN__
227  res = recv(socket, chr, MAXPKTSIZE, 0);
228 #else
229  res = recv(socket, chr, MAXPKTSIZE, MSG_TRUNC);
230 #endif
231  if (res <= 0)
232  throw ConnectionClosed("Connection Closed", HERE);
233  _buffer += std::string(chr, res);
234  if (_update_buffer(delim, i, str))
235  end = true;
236  }
237  _state_timeout = 0;
238  return str;
239  }
240 
241  std::string LocalSocket::_read_line_bin(int socket,
242  std::string& filename,
243  unsigned int pkg_size)
244  {
245  char chr[MAXPKTSIZE];
246  std::string str = "";
247  int res = 1;
248  struct sockaddr_un addr;
249  size_t size;
250  bool end = false;
251 
252  size = sizeof(addr);
253  if (socket < 0)
254  throw NoConnection("No Socket", HERE);
255  if (_buffer.size() >= 2 && !pkg_size)
256  {
257  pkg_size = (unsigned char)_buffer[0] * 256 + (unsigned char)_buffer[1];
258  _buffer = _buffer.substr(2, _buffer.size() - 2);
259  }
260  if (pkg_size && _buffer.size() >= pkg_size)
261  {
262  str = _buffer.substr(0, pkg_size);
263  _buffer = _buffer.substr(pkg_size, _buffer.size() - pkg_size);
264  }
265  else
266  while (!end)
267  {
268 #ifdef __CYGWIN__
269  res = recvfrom(socket, chr, MAXPKTSIZE, 0,
270  (struct sockaddr*)&addr,
271  (socklen_t*)&size);
272 #else
273  res = recvfrom(socket, chr, MAXPKTSIZE, MSG_TRUNC,
274  (struct sockaddr*)&addr,
275  (socklen_t*)&size);
276 #endif
277  if (res <= 0)
278  throw ConnectionClosed("Connection Closed", HERE);
279  // _buffer += all octets received
280  _buffer += std::string(chr, res).substr(0, res);
281  if (!pkg_size)
282  {
283  // extract size from _buffer and reduce it
284  pkg_size = (unsigned char)_buffer[0] * 256 +
285  (unsigned char)_buffer[1];
286  _buffer = _buffer.substr(2, _buffer.size() - 2);
287  }
288  if (_buffer.size() > pkg_size - str.size())
289  {
290  str += _buffer.substr(0, pkg_size - str.size());
291  _buffer = _buffer.substr(pkg_size - str.size(),
292  _buffer.size() - pkg_size - str.size());
293  }
294  else
295  {
296  str += _buffer;
297  _buffer = "";
298  }
299  if (str.size() >= pkg_size)
300  end = true;
301  }
302  filename = std::string(addr.sun_path);
303  return str;
304  }
305 
306  void LocalSocket::writeto(const std::string& str,
307  const std::string& filename)
308  {
309  if (_proto_kind == binary)
310  _write_str_bin(_socket, str, filename);
311  else
312  _write_str(_socket, str, filename);
313  }
314 
315  std::string LocalSocket::readn(unsigned int size)
316  {
317  // _read_line_bin is bufferised with the same buffer as textual
318  // protocols, so this function can be used for binary and text
319  // protocols.
320  return _read_line_bin(_socket, size);
321  }
322 
323  std::string LocalSocket::readn(int timeout, unsigned int size)
324  {
325  if (!size || size > _buffer.size())
326  _set_timeout(true, _socket, timeout);
327  // _read_line_bin is bufferised with the same buffer as textual
328  // protocols, so this function can be used for binary and text
329  // protocols.
330  return _read_line_bin(_socket, size);
331  }
332 
333  std::string LocalSocket::readn(std::string& filename, unsigned int size)
334  {
335  // _read_line_bin is bufferised with the same buffer as textual
336  // protocols, so this function can be used for binary and text
337  // protocols.
338  return _read_line_bin(_socket, filename, size);
339  }
340 
341  std::string LocalSocket::readn(std::string& filename,
342  int timeout, unsigned int size)
343  {
344  if (!size || size > _buffer.size())
345  _set_timeout(true, _socket, timeout);
346  // _read_line_bin is bufferised with the same buffer as textual
347  // protocols, so this function can be used for binary and text
348  // protocols.
349  return _read_line_bin(_socket, filename, size);
350  }
351 
352  std::string LocalSocket::read()
353  {
354  if (_proto_kind == binary)
355  return _read_line_bin(_socket, 0);
356  else
357  return _read_line(_socket);
358  }
359 
360  std::string LocalSocket::read(int timeout)
361  {
362  if (_proto_kind == binary)
363  {
364  _set_timeout(true, _socket, timeout);
365  return _read_line_bin(_socket, 0);
366  }
367  else
368  {
369  _state_timeout = timeout;
370  return _read_line(_socket);
371  }
372  }
373 
374  std::string LocalSocket::read(std::string& filename)
375  {
376  if (_proto_kind)
377  return _read_line_bin(_socket, filename, 0);
378  else
379  return _read_line(_socket, filename);
380  }
381 
382  std::string LocalSocket::read(std::string& filename, int timeout)
383  {
384  if (_proto_kind == binary)
385  {
386  _set_timeout(true, _socket, timeout);
387  return _read_line_bin(_socket, filename, 0);
388  }
389  else
390  {
391  _state_timeout = timeout;
392  return _read_line(_socket, filename);
393  }
394  }
395 }
396 
397 #endif
std::string _filename
Definition: localsocket.hh:224
Network namespace represent all networks connection.
Definition: localsocket.cc:32
void _close(int socket) const
Close a connnection.
Definition: socket.cc:167
void init(const std::string &filename)
Here is an example of named server server using libsocket :
Definition: localsocket.cc:34
void writeto(const std::string &str, const std::string &filename)
function used to send a msg to a specific named socket
Definition: localsocket.cc:306
std::string _read_line_bin(int socket, unsigned int size)
Get a line from socket (when used with binary protocol)
Definition: localsocket.cc:157
void _set_timeout(bool enable, int socket, int timeout)
set a timeout on a socket
Definition: socket.cc:272
#define SENDTO_FLAGS
Definition: socket.hh:48
std::string _buffer
Definition: socket.hh:202
PROTO_KIND _proto_kind
Definition: socket.hh:199
unsigned _state_timeout
Definition: socket.hh:192
void _write_str(int socket, const std::string &str, const std::string &filename) const
Write a string to a socket to a particular named socket (when used with textual protocol) ...
Definition: localsocket.cc:68
bool _update_buffer(std::pair< int, int > &delim, int &i, std::string &str)
look delimiter and remove delimiter at begining of buffer if needed
Definition: socket.hxx:45
void _write_str_bin(int socket, const std::string &str, const std::string &filename) const
Write a string to a socket to a particular named socket (when used with binary protocol) ...
Definition: localsocket.cc:93
std::string _read_line(int socket)
Get a line from socket (when used with textual protocol)
Definition: localsocket.cc:212
std::string read()
function used by >> operator (read a string on current socket)
Definition: localsocket.cc:352
#define HERE
int _bind(const std::string &filename)
Initialize a local socket connection (server in UDP) create a named socket with name filename...
Definition: localsocket.cc:49
std::string readn(unsigned int size)
read a string from socket
Definition: localsocket.cc:315
void close()
connect to a local socket (client)
Definition: localsocket.cc:40