libsocket 1.5
|
00001 /* 00002 ** localsocket.cc 00003 ** Login : Julien Lemoine <speedblue@happycoders.org> 00004 ** Started on Sun May 11 22:19:51 2003 Julien Lemoine 00005 ** $Id: localsocket.cc,v 1.9 2004/11/14 19:37:46 speedblue Exp $ 00006 ** 00007 ** Copyright (C) 2003,2004 Julien Lemoine 00008 ** This program is free software; you can redistribute it and/or modify 00009 ** it under the terms of the GNU Lesser General Public License as published by 00010 ** the Free Software Foundation; either version 2 of the License, or 00011 ** (at your option) any later version. 00012 ** 00013 ** This program is distributed in the hope that it will be useful, 00014 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 ** GNU Lesser General Public License for more details. 00017 ** 00018 ** You should have received a copy of the GNU Lesser General Public License 00019 ** along with this program; if not, write to the Free Software 00020 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00021 */ 00022 00023 #include "localsocket.hh" 00024 00025 #ifndef LIBSOCKET_WIN 00026 00027 #include <sys/types.h> 00028 #include <sys/un.h> 00029 #include <cstddef> 00030 #include "socket.hxx" 00031 00032 namespace Network 00033 { 00034 void LocalSocket::init(const std::string& filename) 00035 { 00036 _socket = _bind(filename); 00037 _filename = filename; 00038 } 00039 00040 void LocalSocket::close() 00041 { 00042 if (_socket > 0) 00043 _close(_socket); 00044 _socket = 0; 00045 unlink(_filename.c_str()); 00046 _filename = ""; 00047 } 00048 00049 int LocalSocket::_bind(const std::string& filename) 00050 { 00051 int s; 00052 struct sockaddr_un name; 00053 size_t size; 00054 00055 s = socket(PF_UNIX, SOCK_DGRAM, 0); 00056 if (s < 0) 00057 throw NoConnection("Socket error", HERE); 00058 name.sun_family = AF_UNIX; 00059 strncpy(name.sun_path, filename.c_str(), sizeof (name.sun_path)); 00060 name.sun_path[sizeof (name.sun_path) - 1] = '\0'; 00061 size = (offsetof (struct sockaddr_un, sun_path) 00062 + strlen (name.sun_path) + 1); 00063 if (bind (s, (struct sockaddr *) &name, size) < 0) 00064 throw BindError("Bind error", HERE); 00065 return s; 00066 } 00067 00068 void LocalSocket::_write_str(int socket, const std::string& str, 00069 const std::string& filename) const 00070 { 00071 int res = 1; 00072 const char *buf = str.c_str(); 00073 unsigned int count = 0; 00074 struct sockaddr_un name; 00075 00076 name.sun_family = AF_UNIX; 00077 strncpy(name.sun_path, filename.c_str(), sizeof (name.sun_path)); 00078 name.sun_path[sizeof (name.sun_path) - 1] = '\0'; 00079 00080 if (socket < 0) 00081 throw NoConnection("No Socket", HERE); 00082 while (res && count < str.size()) 00083 { 00084 res = sendto(socket, buf + count, 00085 str.size() - count, SENDTO_FLAGS, 00086 (const struct sockaddr*)&name, sizeof(name)); 00087 if (res <= 0) 00088 throw ConnectionClosed("Connection Closed", HERE); 00089 count += res; 00090 } 00091 } 00092 00093 void LocalSocket::_write_str_bin(int socket, const std::string& str, 00094 const std::string& filename) const 00095 { 00096 int res = 1; 00097 unsigned int count = 0; 00098 struct sockaddr_un name; 00099 char buf[str.size() + 2]; 00100 00101 buf[0] = str.size() / 256; 00102 buf[1] = str.size() % 256; 00103 memcpy(buf + 2, str.c_str(), str.size()); 00104 name.sun_family = AF_UNIX; 00105 strncpy(name.sun_path, filename.c_str(), sizeof (name.sun_path)); 00106 name.sun_path[sizeof (name.sun_path) - 1] = DEFAULT_DELIM; 00107 00108 if (socket < 0) 00109 throw NoConnection("No Socket", HERE); 00110 while (res && count < str.size() + 2) 00111 { 00112 res = sendto(socket, buf + count, str.size() + 2 - count, SENDTO_FLAGS, 00113 (const struct sockaddr*)&name, sizeof(name)); 00114 if (res <= 0) 00115 throw ConnectionClosed("Connection Closed", HERE); 00116 count += res; 00117 } 00118 } 00119 00120 std::string LocalSocket::_read_line(int socket, 00121 std::string& filename) 00122 { 00123 char chr[MAXPKTSIZE]; 00124 std::string str = ""; 00125 int res = 1, i; 00126 std::pair<int, int> delim; 00127 struct sockaddr_un addr; 00128 size_t size; 00129 bool end = false; 00130 00131 size = sizeof(addr); 00132 if (socket < 0) 00133 throw NoConnection("No Socket", HERE); 00134 if (!_update_buffer(delim, i, str)) 00135 while (!end) 00136 { 00137 #ifdef __CYGWIN__ 00138 res = recvfrom(socket, chr, MAXPKTSIZE, 0, 00139 (struct sockaddr*)&addr, 00140 (socklen_t*)&size); 00141 #else 00142 res = recvfrom(socket, chr, MAXPKTSIZE, MSG_TRUNC, 00143 (struct sockaddr*)&addr, 00144 (socklen_t*)&size); 00145 #endif 00146 if (res <= 0) 00147 throw ConnectionClosed("Connection Closed", HERE); 00148 _buffer += std::string(chr, res); 00149 if (_update_buffer(delim, i, str)) 00150 end = true; 00151 } 00152 filename = std::string(addr.sun_path); 00153 _state_timeout = 0; 00154 return str; 00155 } 00156 00157 std::string LocalSocket::_read_line_bin(int socket, unsigned int size) 00158 { 00159 char chr[MAXPKTSIZE]; 00160 std::string str = ""; 00161 int res = 1; 00162 bool end = false; 00163 00164 if (socket < 0) 00165 throw NoConnection("No Socket", HERE); 00166 if (_buffer.size() >= 2 && !size) 00167 { 00168 size = (unsigned char)_buffer[0] * 256 + (unsigned char)_buffer[1]; 00169 _buffer = _buffer.substr(2, _buffer.size() - 2); 00170 } 00171 if (size && _buffer.size() >= size) 00172 { 00173 str = _buffer.substr(0, size); 00174 _buffer = _buffer.substr(size, _buffer.size() - size); 00175 } 00176 else 00177 while (!end) 00178 { 00179 memset(chr, 0, MAXPKTSIZE); 00180 #ifdef __CYGWIN__ 00181 res = recv(socket, chr, MAXPKTSIZE, 0); 00182 #else 00183 res = recv(socket, chr, MAXPKTSIZE, MSG_TRUNC); 00184 #endif 00185 if (res <= 0) 00186 throw ConnectionClosed("Connection Closed", HERE); 00187 // _buffer += all octets received 00188 _buffer += std::string(chr, res); 00189 if (!size) 00190 { 00191 // extract size from _buffer and reduce it 00192 size = (unsigned char)_buffer[0] * 256 + (unsigned char)_buffer[1]; 00193 _buffer = _buffer.substr(2, _buffer.size() - 2); 00194 } 00195 if (_buffer.size() > size - str.size()) 00196 { 00197 str += _buffer.substr(0, size - str.size()); 00198 _buffer = _buffer.substr(size - str.size(), 00199 _buffer.size() - size - str.size()); 00200 } 00201 else 00202 { 00203 str += _buffer; 00204 _buffer = ""; 00205 } 00206 if (str.size() >= size) 00207 end = true; 00208 } 00209 return str; 00210 } 00211 00212 std::string LocalSocket::_read_line(int socket) 00213 { 00214 char chr[MAXPKTSIZE]; 00215 std::string str = ""; 00216 int res = 1, i; 00217 std::pair<int, int> delim; 00218 bool end = false; 00219 00220 if (socket < 0) 00221 throw NoConnection("No Socket", HERE); 00222 if (!_update_buffer(delim, i, str)) 00223 while (!end) 00224 { 00225 memset(chr, 0, MAXPKTSIZE); 00226 #ifdef __CYGWIN__ 00227 res = recv(socket, chr, MAXPKTSIZE, 0); 00228 #else 00229 res = recv(socket, chr, MAXPKTSIZE, MSG_TRUNC); 00230 #endif 00231 if (res <= 0) 00232 throw ConnectionClosed("Connection Closed", HERE); 00233 _buffer += std::string(chr, res); 00234 if (_update_buffer(delim, i, str)) 00235 end = true; 00236 } 00237 _state_timeout = 0; 00238 return str; 00239 } 00240 00241 std::string LocalSocket::_read_line_bin(int socket, 00242 std::string& filename, 00243 unsigned int pkg_size) 00244 { 00245 char chr[MAXPKTSIZE]; 00246 std::string str = ""; 00247 int res = 1; 00248 struct sockaddr_un addr; 00249 size_t size; 00250 bool end = false; 00251 00252 size = sizeof(addr); 00253 if (socket < 0) 00254 throw NoConnection("No Socket", HERE); 00255 if (_buffer.size() >= 2 && !pkg_size) 00256 { 00257 pkg_size = (unsigned char)_buffer[0] * 256 + (unsigned char)_buffer[1]; 00258 _buffer = _buffer.substr(2, _buffer.size() - 2); 00259 } 00260 if (pkg_size && _buffer.size() >= pkg_size) 00261 { 00262 str = _buffer.substr(0, pkg_size); 00263 _buffer = _buffer.substr(pkg_size, _buffer.size() - pkg_size); 00264 } 00265 else 00266 while (!end) 00267 { 00268 #ifdef __CYGWIN__ 00269 res = recvfrom(socket, chr, MAXPKTSIZE, 0, 00270 (struct sockaddr*)&addr, 00271 (socklen_t*)&size); 00272 #else 00273 res = recvfrom(socket, chr, MAXPKTSIZE, MSG_TRUNC, 00274 (struct sockaddr*)&addr, 00275 (socklen_t*)&size); 00276 #endif 00277 if (res <= 0) 00278 throw ConnectionClosed("Connection Closed", HERE); 00279 // _buffer += all octets received 00280 _buffer += std::string(chr, res).substr(0, res); 00281 if (!pkg_size) 00282 { 00283 // extract size from _buffer and reduce it 00284 pkg_size = (unsigned char)_buffer[0] * 256 + 00285 (unsigned char)_buffer[1]; 00286 _buffer = _buffer.substr(2, _buffer.size() - 2); 00287 } 00288 if (_buffer.size() > pkg_size - str.size()) 00289 { 00290 str += _buffer.substr(0, pkg_size - str.size()); 00291 _buffer = _buffer.substr(pkg_size - str.size(), 00292 _buffer.size() - pkg_size - str.size()); 00293 } 00294 else 00295 { 00296 str += _buffer; 00297 _buffer = ""; 00298 } 00299 if (str.size() >= pkg_size) 00300 end = true; 00301 } 00302 filename = std::string(addr.sun_path); 00303 return str; 00304 } 00305 00306 void LocalSocket::writeto(const std::string& str, 00307 const std::string& filename) 00308 { 00309 if (_proto_kind == binary) 00310 _write_str_bin(_socket, str, filename); 00311 else 00312 _write_str(_socket, str, filename); 00313 } 00314 00315 std::string LocalSocket::readn(unsigned int size) 00316 { 00317 // _read_line_bin is bufferised with the same buffer as textual 00318 // protocols, so this function can be used for binary and text 00319 // protocols. 00320 return _read_line_bin(_socket, size); 00321 } 00322 00323 std::string LocalSocket::readn(int timeout, unsigned int size) 00324 { 00325 if (!size || size > _buffer.size()) 00326 _set_timeout(true, _socket, timeout); 00327 // _read_line_bin is bufferised with the same buffer as textual 00328 // protocols, so this function can be used for binary and text 00329 // protocols. 00330 return _read_line_bin(_socket, size); 00331 } 00332 00333 std::string LocalSocket::readn(std::string& filename, unsigned int size) 00334 { 00335 // _read_line_bin is bufferised with the same buffer as textual 00336 // protocols, so this function can be used for binary and text 00337 // protocols. 00338 return _read_line_bin(_socket, filename, size); 00339 } 00340 00341 std::string LocalSocket::readn(std::string& filename, 00342 int timeout, unsigned int size) 00343 { 00344 if (!size || size > _buffer.size()) 00345 _set_timeout(true, _socket, timeout); 00346 // _read_line_bin is bufferised with the same buffer as textual 00347 // protocols, so this function can be used for binary and text 00348 // protocols. 00349 return _read_line_bin(_socket, filename, size); 00350 } 00351 00352 std::string LocalSocket::read() 00353 { 00354 if (_proto_kind == binary) 00355 return _read_line_bin(_socket, 0); 00356 else 00357 return _read_line(_socket); 00358 } 00359 00360 std::string LocalSocket::read(int timeout) 00361 { 00362 if (_proto_kind == binary) 00363 { 00364 _set_timeout(true, _socket, timeout); 00365 return _read_line_bin(_socket, 0); 00366 } 00367 else 00368 { 00369 _state_timeout = timeout; 00370 return _read_line(_socket); 00371 } 00372 } 00373 00374 std::string LocalSocket::read(std::string& filename) 00375 { 00376 if (_proto_kind) 00377 return _read_line_bin(_socket, filename, 0); 00378 else 00379 return _read_line(_socket, filename); 00380 } 00381 00382 std::string LocalSocket::read(std::string& filename, int timeout) 00383 { 00384 if (_proto_kind == binary) 00385 { 00386 _set_timeout(true, _socket, timeout); 00387 return _read_line_bin(_socket, filename, 0); 00388 } 00389 else 00390 { 00391 _state_timeout = timeout; 00392 return _read_line(_socket, filename); 00393 } 00394 } 00395 } 00396 00397 #endif