Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

localsocket.cc

Go to the documentation of this file.
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.8 2004/06/03 03:02:46 nuntiux 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 "socket.hxx"
00030 
00031 namespace Network
00032 {
00033   void  LocalSocket::init(const std::string& filename)
00034   {
00035     _socket = _bind(filename);
00036     _filename = filename;
00037   }
00038 
00039   void  LocalSocket::close()
00040   {
00041     if (_socket > 0)
00042       _close(_socket);
00043     _socket = 0;
00044     unlink(_filename.c_str());
00045     _filename = "";
00046   }
00047 
00048   int           LocalSocket::_bind(const std::string& filename)
00049   {
00050     int                         s;
00051     struct sockaddr_un          name;
00052     size_t                      size;
00053 
00054     s = socket(PF_UNIX, SOCK_DGRAM, 0);
00055     if (s < 0)
00056       throw NoConnection("Socket error", HERE);
00057     name.sun_family = AF_UNIX;
00058     strncpy(name.sun_path, filename.c_str(), sizeof (name.sun_path));
00059     name.sun_path[sizeof (name.sun_path) - 1] = '\0';
00060     size = (offsetof (struct sockaddr_un, sun_path)
00061             + strlen (name.sun_path) + 1);
00062     if (bind (s, (struct sockaddr *) &name, size) < 0)
00063       throw BindError("Bind error", HERE);
00064     return s;
00065   }
00066 
00067   void  LocalSocket::_write_str(int socket, const std::string& str,
00068                                 const std::string& filename) const
00069   {
00070     int                         res = 1;
00071     const char                  *buf = str.c_str();
00072     unsigned int                count = 0;
00073     struct sockaddr_un          name;
00074 
00075     name.sun_family = AF_UNIX;
00076     strncpy(name.sun_path, filename.c_str(), sizeof (name.sun_path));
00077     name.sun_path[sizeof (name.sun_path) - 1] = '\0';
00078 
00079     if (socket < 0)
00080       throw NoConnection("No Socket", HERE);
00081     while (res && count < str.size())
00082       {
00083         res = sendto(socket, buf + count,
00084                      str.size() - count, SENDTO_FLAGS,
00085                      (const struct sockaddr*)&name, sizeof(name));
00086         if (res <= 0)
00087           throw ConnectionClosed("Connection Closed", HERE);
00088         count += res;
00089       }
00090   }
00091 
00092   void  LocalSocket::_write_str_bin(int socket, const std::string& str,
00093                                     const std::string& filename) const
00094   {
00095     int                         res = 1;
00096     unsigned int                count = 0;
00097     struct sockaddr_un          name;
00098     char                        buf[str.size() + 2];
00099 
00100     buf[0] = str.size() / 256;
00101     buf[1] = str.size() % 256;
00102     memcpy(buf + 2, str.c_str(), str.size());
00103     name.sun_family = AF_UNIX;
00104     strncpy(name.sun_path, filename.c_str(), sizeof (name.sun_path));
00105     name.sun_path[sizeof (name.sun_path) - 1] = DEFAULT_DELIM;
00106 
00107     if (socket < 0)
00108       throw NoConnection("No Socket", HERE);
00109     while (res && count < str.size() + 2)
00110       {
00111         res = sendto(socket, buf + count, str.size() + 2 - count, SENDTO_FLAGS,
00112                      (const struct sockaddr*)&name, sizeof(name));
00113         if (res <= 0)
00114           throw ConnectionClosed("Connection Closed", HERE);
00115         count += res;
00116       }
00117   }
00118 
00119   std::string   LocalSocket::_read_line(int socket,
00120                                         std::string& filename)
00121   {
00122     char                chr[MAXPKTSIZE];
00123     std::string         str = "";
00124     int                 res = 1, i;
00125     std::pair<int, int> delim;
00126     struct sockaddr_un  addr;
00127     size_t              size;
00128     bool                end = false;
00129 
00130     size = sizeof(addr);
00131     if (socket < 0)
00132       throw NoConnection("No Socket", HERE);
00133     if (!_update_buffer(delim, i, str))
00134       while (!end)
00135         {
00136 #ifdef __CYGWIN__
00137           res = recvfrom(socket, chr, MAXPKTSIZE, 0,
00138                          (struct sockaddr*)&addr,
00139                          (socklen_t*)&size);
00140 #else
00141           res = recvfrom(socket, chr, MAXPKTSIZE, MSG_TRUNC,
00142                          (struct sockaddr*)&addr,
00143                          (socklen_t*)&size);
00144 #endif
00145           if (res <= 0)
00146             throw ConnectionClosed("Connection Closed", HERE);
00147           _buffer += std::string(chr, res);
00148           if (_update_buffer(delim, i, str))
00149             end = true;
00150         }
00151     filename = std::string(addr.sun_path);
00152     _state_timeout = 0;
00153     return str;
00154   }
00155 
00156   std::string   LocalSocket::_read_line_bin(int socket, unsigned int size)
00157   {
00158     char                chr[MAXPKTSIZE];
00159     std::string         str = "";
00160     int                 res = 1;
00161     bool                end = false;
00162 
00163     if (socket < 0)
00164       throw NoConnection("No Socket", HERE);
00165     if (_buffer.size() >= 2 && !size)
00166       {
00167         size = (unsigned char)_buffer[0] * 256 + (unsigned char)_buffer[1];
00168         _buffer = _buffer.substr(2, _buffer.size() - 2);
00169       }
00170     if (size && _buffer.size() >= size)
00171       {
00172         str = _buffer.substr(0, size);
00173         _buffer = _buffer.substr(size, _buffer.size() - size);
00174       }
00175     else
00176       while (!end)
00177         {
00178           memset(chr, 0, MAXPKTSIZE);
00179 #ifdef __CYGWIN__
00180           res = recv(socket, chr, MAXPKTSIZE, 0);
00181 #else
00182           res = recv(socket, chr, MAXPKTSIZE, MSG_TRUNC);
00183 #endif
00184           if (res <= 0)
00185             throw ConnectionClosed("Connection Closed", HERE);
00186           // _buffer += all octets received
00187           _buffer += std::string(chr, res);
00188           if (!size)
00189             {
00190               // extract size from _buffer and reduce it
00191               size = (unsigned char)_buffer[0] * 256 + (unsigned char)_buffer[1];
00192               _buffer = _buffer.substr(2, _buffer.size() - 2);
00193             }
00194           if (_buffer.size() > size - str.size())
00195             {
00196               str += _buffer.substr(0, size - str.size());
00197               _buffer = _buffer.substr(size - str.size(), 
00198                                        _buffer.size() - size - str.size());
00199             }
00200           else
00201             {
00202               str += _buffer;
00203               _buffer = "";
00204             }
00205           if (str.size() >= size)
00206             end = true;
00207         }
00208     return str;
00209   }
00210 
00211   std::string   LocalSocket::_read_line(int socket)
00212   {
00213     char                chr[MAXPKTSIZE];
00214     std::string         str = "";
00215     int                 res = 1, i;
00216     std::pair<int, int> delim;
00217     bool                end = false;
00218 
00219     if (socket < 0)
00220       throw NoConnection("No Socket", HERE);
00221     if (!_update_buffer(delim, i, str))
00222       while (!end)
00223         {
00224           memset(chr, 0, MAXPKTSIZE);
00225 #ifdef __CYGWIN__
00226           res = recv(socket, chr, MAXPKTSIZE, 0);
00227 #else
00228           res = recv(socket, chr, MAXPKTSIZE, MSG_TRUNC);
00229 #endif
00230           if (res <= 0)
00231             throw ConnectionClosed("Connection Closed", HERE);
00232           _buffer += std::string(chr, res);
00233           if (_update_buffer(delim, i, str))
00234             end = true;
00235         }
00236     _state_timeout = 0;
00237     return str;
00238   }
00239 
00240   std::string   LocalSocket::_read_line_bin(int socket,
00241                                             std::string& filename,
00242                                             unsigned int pkg_size)
00243   {
00244     char                chr[MAXPKTSIZE];
00245     std::string         str = "";
00246     int                 res = 1;
00247     struct sockaddr_un  addr;
00248     size_t              size;
00249     bool                end = false;
00250 
00251     size = sizeof(addr);
00252     if (socket < 0)
00253       throw NoConnection("No Socket", HERE);
00254     if (_buffer.size() >= 2 && !pkg_size)
00255       {
00256         pkg_size = (unsigned char)_buffer[0] * 256 + (unsigned char)_buffer[1];
00257         _buffer = _buffer.substr(2, _buffer.size() - 2);
00258       }
00259     if (pkg_size && _buffer.size() >= pkg_size)
00260       {
00261         str = _buffer.substr(0, pkg_size);
00262         _buffer = _buffer.substr(pkg_size, _buffer.size() - pkg_size);
00263       }
00264     else
00265       while (!end)
00266         {
00267 #ifdef __CYGWIN__
00268           res = recvfrom(socket, chr, MAXPKTSIZE, 0,
00269                          (struct sockaddr*)&addr,
00270                          (socklen_t*)&size);
00271 #else
00272           res = recvfrom(socket, chr, MAXPKTSIZE, MSG_TRUNC,
00273                          (struct sockaddr*)&addr,
00274                          (socklen_t*)&size);
00275 #endif
00276           if (res <= 0)
00277             throw ConnectionClosed("Connection Closed", HERE);
00278           // _buffer += all octets received
00279           _buffer += std::string(chr, res).substr(0, res);
00280           if (!pkg_size)
00281             {
00282               // extract size from _buffer and reduce it
00283               pkg_size = (unsigned char)_buffer[0] * 256 + 
00284                 (unsigned char)_buffer[1];
00285               _buffer = _buffer.substr(2, _buffer.size() - 2);
00286             }
00287           if (_buffer.size() > pkg_size - str.size())
00288             {
00289               str += _buffer.substr(0, pkg_size - str.size());
00290               _buffer = _buffer.substr(pkg_size - str.size(), 
00291                                        _buffer.size() - pkg_size - str.size());
00292             }
00293           else
00294             {
00295               str += _buffer;
00296               _buffer = "";
00297             }
00298           if (str.size() >= pkg_size)
00299             end = true;
00300         }
00301     filename = std::string(addr.sun_path);
00302     return str;
00303   }
00304 
00305   void LocalSocket::writeto(const std::string& str,
00306                             const std::string& filename)
00307   {
00308     if (_proto_kind == binary)
00309       _write_str_bin(_socket, str, filename);
00310     else
00311       _write_str(_socket, str, filename);
00312   }
00313 
00314   std::string   LocalSocket::readn(unsigned int size)
00315   {
00316     // _read_line_bin is bufferised with the same buffer as textual
00317     // protocols, so this function can be used for binary and text
00318     // protocols.
00319     return _read_line_bin(_socket, size);
00320   }
00321 
00322   std::string   LocalSocket::readn(int timeout, unsigned int size)
00323   {
00324     if (!size || size > _buffer.size())
00325       _set_timeout(true, _socket, timeout);
00326     // _read_line_bin is bufferised with the same buffer as textual
00327     // protocols, so this function can be used for binary and text
00328     // protocols.
00329     return _read_line_bin(_socket, size);
00330   }
00331 
00332   std::string   LocalSocket::readn(std::string& filename, unsigned int size)
00333   {
00334     // _read_line_bin is bufferised with the same buffer as textual
00335     // protocols, so this function can be used for binary and text
00336     // protocols.
00337     return _read_line_bin(_socket, filename, size);
00338   }
00339 
00340   std::string   LocalSocket::readn(std::string& filename,
00341                                    int timeout, unsigned int size)
00342   {
00343     if (!size || size > _buffer.size())
00344       _set_timeout(true, _socket, timeout);
00345     // _read_line_bin is bufferised with the same buffer as textual
00346     // protocols, so this function can be used for binary and text
00347     // protocols.
00348     return _read_line_bin(_socket, filename, size);
00349   }
00350 
00351   std::string   LocalSocket::read()
00352   {
00353     if (_proto_kind == binary)
00354       return _read_line_bin(_socket, 0);
00355     else
00356       return _read_line(_socket);
00357   }
00358 
00359   std::string   LocalSocket::read(int timeout)
00360   {
00361     if (_proto_kind == binary)
00362       {
00363         _set_timeout(true, _socket, timeout);
00364         return _read_line_bin(_socket, 0);
00365       }
00366     else
00367       {
00368         _state_timeout = timeout;
00369         return _read_line(_socket);
00370       }
00371   }
00372 
00373   std::string   LocalSocket::read(std::string& filename)
00374   {
00375     if (_proto_kind)
00376       return _read_line_bin(_socket, filename, 0);
00377     else
00378       return _read_line(_socket, filename);
00379   }
00380 
00381   std::string   LocalSocket::read(std::string& filename, int timeout)
00382   {
00383     if (_proto_kind == binary)
00384       {
00385         _set_timeout(true, _socket, timeout);
00386         return _read_line_bin(_socket, filename, 0);
00387       }
00388     else
00389       {
00390         _state_timeout = timeout;
00391         return _read_line(_socket, filename);
00392       }
00393   }
00394 }
00395 
00396 #endif

Generated on Fri Apr 8 06:13:01 2005 for libsocket by  doxygen 1.4.0