linux/ntcpsocket.cpp

00001 // LICENSE: (Please see the file COPYING for details)
00002 //
00003 // NUS - Nemesis Utilities System: A C++ application development framework 
00004 // Copyright (C) 2006, 2008 Otavio Rodolfo Piske
00005 //
00006 //  This file is part of NUS
00007 //
00008 //  This library is free software; you can redistribute it and/or
00009 //  modify it under the terms of the GNU Lesser General Public
00010 //  License as published by the Free Software Foundation version 2.1
00011 //  of the License.
00012 //
00013 //  This library 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 GNU
00016 //  Lesser General Public License for more details.
00017 //
00018 //  You should have received a copy of the GNU Lesser General Public
00019 //  License along with this library; if not, write to the Free Software
00020 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021 //
00022 #include "ntcpsocket.h"
00023 
00024 NTcpSocket::NTcpSocket(void)
00025       : NAbstractSocket(),
00026       m_addr(),
00027       m_sock(-1)
00028 {
00029       init();
00030 }
00031 
00032 NTcpSocket::NTcpSocket(NHostAddress &host)
00033       : NAbstractSocket(host),
00034       m_addr(),
00035       m_sock(-1)
00036 {
00037       init();
00038 }
00039 
00040 
00041 NTcpSocket::NTcpSocket(const NString &host, nuint16 port)
00042       : NAbstractSocket(host, port),
00043       m_addr(),
00044       m_sock(-1)
00045 {
00046       init();
00047 }
00048 
00049 NTcpSocket::NTcpSocket(nuint16 timeout, nint32 sock, struct sockaddr_in client)
00050       : NAbstractSocket(),
00051       m_addr(),
00052       m_sock(sock)
00053 {
00054       init();
00055       setTimeout(timeout);
00056       m_addr = client;
00057       
00058       m_host.setAddress(reinterpret_cast<struct sockaddr *>(&m_addr));
00059       setPort(ntohs(m_addr.sin_port));
00060 }
00061 
00062 NTcpSocket::~NTcpSocket(void) {
00063 
00064 }
00065 
00066 void NTcpSocket::setPort(nint16 port) { 
00067       NAbstractSocket::setPort(port);
00068       
00069       m_addr.sin_port = htons(m_port); 
00070 }
00071 
00072 void NTcpSocket::setSocketOptions(nint32 opt) { 
00073       int val = 1;
00074       
00075       NAbstractSocket::setSocketOptions(opt);
00076       
00077       // Will force binding and won't fail unless there's really is an active
00078       // listening socket. I.E.: state == LISTENING. 
00079       if (m_opt & REUSE_ADDRESS) { 
00080             setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
00081       }
00082       
00083       // Enables keep-alive messages on connection oriented protocols like, tcp ;)
00084       if (m_opt & KEEPALIVE) { 
00085             setsockopt(m_sock, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
00086       }
00087 }
00088 
00089 
00090 void NTcpSocket::init(void) {
00091       memset(&m_addr, 0, sizeof(m_addr));
00092       
00093       m_addr.sin_family = AF_INET;
00094 }
00095 
00096 void NTcpSocket::open(void) { 
00097       m_sock = socket(PF_INET, SOCK_STREAM, 0);
00098       if (!m_sock == -1) { 
00099             throw NNetworkException(nerror(errno), "", NException::NETWORK, 
00100                         NNetworkException::SOCKET_INIT_FAILED);
00101       }
00102       
00103 }
00104 
00105 void NTcpSocket::closeDevice(void) { 
00106       disconnectFromHost();
00107 }
00108 
00109 void NTcpSocket::disconnectFromHost(void) { 
00110       close(m_sock);
00111       m_sock = 0;
00112 }
00113 
00114 void NTcpSocket::connectToHost() { 
00115       int ret = 0;
00116       
00117       m_host.resolve();
00118       inet_aton(m_host.toString().toChar(), &m_addr.sin_addr);
00119       if (m_addr.sin_addr.s_addr == INADDR_NONE) {
00120             throw NNetworkException("Bad Address", m_host.toString(),
00121                   NException::NETWORK, NNetworkException::SOCKET_INIT_FAILED);
00122       }
00123       
00124       ret = connect(m_sock, reinterpret_cast<struct sockaddr *>(&m_addr),
00125                   sizeof(m_addr));
00126       if (ret == -1) { 
00127             NString msg = nerror(errno);
00128             
00129             msg += NSTR(": ") + m_host.toString() + NSTR(":") + NString::number(m_port);
00130             throw NNetworkException(msg, m_host.toString(), 
00131                   NException::NETWORK, NNetworkException::CONNECTION_FAILED);
00132       }
00133 }
00134 
00135 void NTcpSocket::execBind(void) { 
00136       int ret = 0;
00137       
00138       if (m_host.isNull()) { 
00139             m_addr.sin_addr.s_addr = INADDR_ANY;
00140       }
00141       else {
00142             m_addr.sin_addr.s_addr = inet_addr(m_host.toString().toChar());
00143             if (m_addr.sin_addr.s_addr == INADDR_NONE) {
00144                   throw NNetworkException("Bad Address", m_host.toString(),
00145                         NException::NETWORK, NNetworkException::SOCKET_INIT_FAILED);
00146             }
00147       }
00148       
00149       ret = bind(m_sock, reinterpret_cast<const struct sockaddr *>(&m_addr),
00150                sizeof(m_addr));
00151       if (ret == -1) { 
00152             NString msg = nerror(errno);
00153             
00154             msg += NSTR(": ") + m_host.toString() + NSTR(":") + NString::number(m_port);
00155             throw NNetworkException(msg, m_host.toString(), NException::NETWORK,
00156                   NNetworkException::SOCKET_INIT_FAILED);
00157       }
00158 }
00159 
00160 
00161 void NTcpSocket::setPeer(struct sockaddr_in addr) {
00162       m_addr = addr;
00163 }
00164 
00165 
00166 void NTcpSocket::setSock(int sock) {
00167       m_sock = sock;
00168 }
00169 
00170 void NTcpSocket::setupNewSocket(NTcpSocket *sock, struct sockaddr_in addr) {
00171       assert(sock);
00172       
00173       sock->setTimeout(m_timeout);
00174       sock->setReadBufferSize(m_readBufferSize);
00175       sock->setHost(m_host);
00176 }
00177 
00178 
00179 void NTcpSocket::execListen(void) {
00180       int ret = 0;
00181       
00182       execBind();
00183       ret = listen(m_sock, m_maxPendingConn);
00184       if (ret == -1) { 
00185             NString msg = nerror(errno);
00186             
00187             msg += NSTR(": ") + m_host.toString() + NSTR(":") + NString::number(m_port);
00188             throw NException(msg , NException::NETWORK);
00189       }
00190       
00191 }
00192 
00193 
00194 NTcpSocket *NTcpSocket::waitForConnected(void) { 
00195       int client  = 0;
00196       NTcpSocket *ret = NULL;
00197       struct sockaddr_in cli_addr;
00198       socklen_t len_inet = 0;
00199       
00200       len_inet = sizeof(cli_addr);
00201       client = accept(m_sock, reinterpret_cast<struct sockaddr *>(&cli_addr), 
00202                    &len_inet);
00203       if (client == -1) {
00204             delete ret;
00205             NString msg = nerror(errno);
00206             
00207             msg += NSTR(": ") + m_host.toString() + NSTR(":") + NString::number(m_port);
00208             throw NNetworkException(msg , m_host.toString(), 
00209                         NException::NETWORK, NNetworkException::SOCKET_INIT_FAILED);
00210       }
00211       
00212       ret = new NTcpSocket(m_timeout, client, cli_addr);
00213       return ret;
00214       
00215 }
00216 
00217 
00218 NHostAddress NTcpSocket::peerAddress(void) const { 
00219       NHostAddress ret;
00220       
00221       ret.setAddress(reinterpret_cast<const struct sockaddr *>(&m_addr));
00222       return ret;
00223 }
00224 
00225 
00226 NString NTcpSocket::peerName(void) const {
00227       return peerAddress().toString();
00228 }
00229 
00230 
00231 nuint16 NTcpSocket::peerPort(void) const {
00232       return ntohs(m_addr.sin_port);
00233 }
00234 
00235 
00236 nint32 NTcpSocket::read(NDataStream *buffer) { 
00237       nint32 bread = 0;
00238       fd_set fd;
00239       timeval timeout;
00240       nint32 sel = 0;
00241       socklen_t len = 0;
00242       nint32 numRead = -1;
00243       char tmp[m_readBufferSize];
00244 
00245       FD_ZERO(&fd);
00246       FD_SET(m_sock, &fd);
00247       
00248       timeout.tv_sec = m_timeout;
00249       timeout.tv_usec = 0;
00250       
00251       sel = select(m_sock + 1, &fd, NULL, NULL, &timeout);
00252       if (sel < 0) {
00253             throw NNetworkException(nerror(errno), m_host.toString(), 
00254                               NException::NETWORK, NNetworkException::SOCK_ERROR);
00255       }
00256       
00257       if (sel == 0) {
00258             return 0;
00259       }
00260       
00261       *buffer = "";
00262       do { 
00263             memset(tmp, 0, sizeof(tmp));
00264 
00265             numRead = recvfrom(m_sock, &tmp, sizeof(tmp), MSG_DONTWAIT,
00266                             reinterpret_cast<struct sockaddr *>(&m_addr),
00267                             &len);
00268             if (numRead < 0) {
00269                   break;
00270             }
00271             else {
00272                   // There's action in a file descriptor but no data to read
00273                   // so it's likely that the remote peer disconnected
00274                   if (sel == 1 && numRead == 0 && bread == 0) {
00275                         return -1;
00276                   }
00277             }
00278             
00279             bread += numRead;
00280             buffer->append(tmp, numRead);
00281       } while (numRead > 0);
00282       
00283       return bread;
00284 }
00285 
00286 
00287 
00288 nint32 NTcpSocket::read(NDataStream *buffer, nuint32 bytes) { 
00289       nuint32 bread = 0;
00290       fd_set fd;
00291       timeval timeout;
00292       nint32 sel = 0;
00293       socklen_t len = 0;
00294       nint32 numRead = -1;
00295       char tmp[1];
00296 
00297       FD_ZERO(&fd);
00298       FD_SET(m_sock, &fd);
00299       
00300       timeout.tv_sec = m_timeout;
00301       timeout.tv_usec = 0;
00302       
00303       sel = select(m_sock + 1, &fd, NULL, NULL, &timeout);
00304       if (sel < 0) {
00305             throw NNetworkException(nerror(errno), m_host.toString(), 
00306                               NException::NETWORK, NNetworkException::SOCK_ERROR);
00307       }
00308       
00309       if (sel == 0) {
00310             // timedout
00311             return 0;
00312       }
00313       
00314       *buffer = "";
00315       do { 
00316             memset(tmp, 0, sizeof(tmp));
00317 
00318             numRead = recvfrom(m_sock, &tmp, 1, MSG_DONTWAIT,
00319                             reinterpret_cast<struct sockaddr *>(&m_addr),
00320                             &len);
00321             if (numRead < 0) {
00322                   break;
00323             }
00324             else {
00325                   // There's action in a file descriptor but no data to read
00326                   // it's likely that the remote peer disconnected
00327                   if (sel == 1 && numRead == 0 && bread == 0) {
00328                         return -1;
00329                   }
00330 
00331             }
00332             
00333             bread += numRead;
00334             buffer->append(tmp, numRead);
00335       } while (numRead > 0 && bread < bytes);
00336       
00337       return bread;
00338 }
00339 
00340 
00341 nint32 NTcpSocket::readLine(NDataStream *buffer) { 
00342       nint32 bread = 0;
00343       fd_set fd;
00344       timeval timeout;
00345       nint32 sel = 0;
00346       socklen_t len = 0;
00347       nint32 numRead = -1;
00348       char tmp[1];
00349 
00350       FD_ZERO(&fd);
00351       FD_SET(m_sock, &fd);
00352       
00353       timeout.tv_sec = m_timeout;
00354       timeout.tv_usec = 0;
00355       
00356       sel = select(m_sock + 1, &fd, NULL, NULL, &timeout);
00357       if (sel < 0) {
00358             throw NNetworkException(nerror(errno), m_host.toString(), 
00359                               NException::NETWORK, NNetworkException::SOCK_ERROR);
00360       }
00361       
00362       if (sel == 0) {
00363             // timedout
00364             return 0;
00365       }
00366       
00367       *buffer = "";
00368       do { 
00369             memset(tmp, 0, sizeof(tmp));
00370 
00371             numRead = recvfrom(m_sock, &tmp, sizeof(tmp), MSG_DONTWAIT,
00372                             reinterpret_cast<struct sockaddr *>(&m_addr),
00373                             &len);
00374 
00375             if (numRead < 0) {
00376                   NDebug::print() << "I did not received an orderly shutdown: "
00377                                     << nerror(errno);
00378                   return -1;
00379             }
00380             else {
00381                   // There's action in a file descriptor but no data to read
00382                   // it's likely that the remote peer disconnected
00383                   if (sel == 1 && numRead == 0 && bread == 0) {
00384                         return -1;
00385                   }
00386 
00387             }
00388             if (tmp[0] == '\n' || tmp[0] == '\0' || numRead < 0) {
00389                   break;
00390             }
00391             
00392             bread += numRead;
00393             buffer->append(tmp, numRead);
00394       } while (numRead > 0);
00395       
00396       return bread;
00397 }
00398 
00399 nint32 NTcpSocket::write(const NDataStream &data, nuint32 bytes) { 
00400       if (bytes == 0) {
00401             return send(m_sock, data.data(), data.size(), MSG_DONTWAIT);
00402       }
00403             
00404       return send(m_sock, data.data(), bytes, MSG_DONTWAIT);
00405 }
00406 
00407 
00408 nint32 NTcpSocket::writeLine(const NDataStream &data, nuint32 bytes) {
00409       NDataStream tmp = data;
00410 
00411       tmp += "\r\n";
00412 
00413       if (bytes == 0) {
00414             return send(m_sock, tmp.data(), tmp.size(), MSG_DONTWAIT);
00415       }
00416             
00417       return send(m_sock, tmp.data(), bytes, MSG_DONTWAIT);
00418 }

Generated on Wed Mar 5 23:10:36 2008 for NemesisUtilitiesSystem by  doxygen 1.5.4