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
32namespace 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)
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
void init(const std::string &filename)
Here is an example of named server server using libsocket :
Definition: localsocket.cc:34
std::string _filename
Definition: localsocket.hh:224
void close()
connect to a local socket (client)
Definition: localsocket.cc:40
std::string _read_line(int socket)
Get a line from socket (when used with textual protocol)
Definition: localsocket.cc:212
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
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 _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
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_bin(int socket, unsigned int size)
Get a line from socket (when used with binary protocol)
Definition: localsocket.cc:157
std::string read()
function used by >> operator (read a string on current socket)
Definition: localsocket.cc:352
void _set_timeout(bool enable, int socket, int timeout)
set a timeout on a socket
Definition: socket.cc:272
std::string _buffer
Definition: socket.hh:202
unsigned _state_timeout
Definition: socket.hh:192
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 _close(int socket) const
Close a connnection.
Definition: socket.cc:167
PROTO_KIND _proto_kind
Definition: socket.hh:199
Network namespace represent all networks connection.
Definition: localsocket.cc:33
@ binary
Definition: socket.hh:75
#define SENDTO_FLAGS
Definition: socket.hh:48
#define HERE