• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/Socket.cpp

00001 /*
00002  *   This file is part of the Standard Portable Library (SPL).
00003  *
00004  *   SPL is free software: you can redistribute it and/or modify
00005  *   it under the terms of the GNU General Public License as published by
00006  *   the Free Software Foundation, either version 3 of the License, or
00007  *   (at your option) any later version.
00008  *
00009  *   SPL is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details.
00013  *
00014  *   You should have received a copy of the GNU General Public License
00015  *   along with SPL.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 #if defined(_WIN32) || defined(_WIN64)
00018 #include <spl/configwin32.h>
00019 #include <stdio.h>
00020 #else
00021 #include <spl/autoconf/config.h>
00022 #endif
00023 
00024 // On some platforms, thread overrides IO routines.
00025 #include <spl/threading/Thread.h>
00026 
00027 #ifdef HAVE_SYS_IOCTL_H
00028 #include <sys/ioctl.h>
00029 #endif
00030 
00031 #include <spl/Environment.h>
00032 #include <ctype.h>
00033 #include <spl/Debug.h>
00034 #include <spl/Exception.h>
00035 #include <spl/Log.h>
00036 #include <spl/net/ServerSocket.h>
00037 #include <spl/net/Socket.h>
00038 #include <spl/io/SocketStream.h>
00039 #include <spl/net/TcpSocket.h>
00040 
00041 bool Socket::m_inited = false;
00042 
00043 void Socket::sinit()
00044 {
00045 #ifdef _WINDOWS
00046         m_inited = true;
00047         WORD wVersionRequested;
00048         WSADATA wsaData;
00049         int err;
00050          
00051         wVersionRequested = MAKEWORD( 2, 2 );
00052          
00053         err = WSAStartup( wVersionRequested, &wsaData );
00054         if ( err != 0 ) 
00055         {
00056                 throw new SocketException(Environment::LastErrorMessage());
00057         }
00058 #endif
00059 }
00060 
00061 void Socket::Init()
00062 {
00063         if ( ! m_inited )
00064         {
00065                 sinit();
00066         }
00067         m_saAddr.sin_family = AF_INET;
00068         m_saAddr.sin_port = htons(0);
00069         m_saAddr.sin_addr.s_addr = htonl(0);
00070         m_errorStatus = 0;
00071         m_closed = false;
00072 }
00073 
00074 Socket::Socket(const Socket& sock)
00075 :       m_saAddr(sock.m_saAddr), 
00076         m_fd(sock.m_fd), 
00077         m_closed(sock.m_closed), 
00078         m_errorStatus(sock.m_errorStatus)
00079 {
00080 }
00081 
00082 Socket& Socket::operator =(const Socket& sock)
00083 {
00084         m_saAddr = sock.m_saAddr;
00085         m_fd = sock.m_fd;
00086         m_closed = sock.m_closed;
00087         m_errorStatus = sock.m_errorStatus;
00088 
00089         return *this;
00090 }
00091 
00092 Socket::Socket()
00093 : m_fd()
00094 {
00095         Init();
00096 }
00097 
00098 Socket::Socket(SOCKET fd, bool dummy)
00099 {
00100         Init();
00101         m_fd = fd;
00102 }
00103 
00109 Socket::Socket ( int port, int family, int streamType, int protocol )
00110 {
00111         Init();
00112         m_fd = ::socket(family, streamType, protocol);
00113         if (m_fd < 0)
00114         {
00115                 throw new SocketException(Environment::LastErrorMessage());
00116         }
00117         m_saAddr.sin_port = htons(port);
00118 }
00119 
00120 Socket::Socket (int port)
00121 {
00122         Init();
00123         m_fd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
00124         if (m_fd < 0)
00125         {
00126                 throw new SocketException(Environment::LastErrorMessage());
00127         }
00128         m_saAddr.sin_port = htons(port);
00129 }
00130 
00131 TcpSocketPtr ServerSocket::Accept()
00132 {
00133         if ( ! m_sock.m_inited )
00134         {
00135                 m_sock.sinit();
00136         }
00137         SOCKET fd;
00138         SOCKADDR_IN saAddr;
00139 #ifdef _WINDOWS
00140         int size = sizeof(saAddr);
00141 #else
00142         socklen_t size = sizeof(saAddr);
00143 #endif
00144         m_sock.m_errorStatus = 0;
00145         fd = ::accept(m_sock.m_fd, (struct sockaddr *)&saAddr, &size);
00146         if ( fd == INVALID_SOCKET )
00147         {
00148                 if (m_sock.IsClosed())
00149                 {
00150                         return TcpSocketPtr();
00151                 }
00152 #ifdef _WINDOWS
00153                 m_sock.m_errorStatus = WSAGetLastError();
00154                 if ( 10004 == m_sock.m_errorStatus )
00155                 {
00156                         return Accept();
00157                 }
00158 #else
00159                 m_sock.m_errorStatus = errno;
00160 #endif
00161                 throw new SocketException(Environment::LastErrorMessage());
00162         }
00163         TcpSocketPtr sock = TcpSocketPtr( new TcpSocket(fd) );
00164         memcpy(&sock->m_sock->m_saAddr, &saAddr, sizeof(saAddr));
00165 
00166         //lookupName(&saAddr, 5, hostName);
00167         
00168         return sock;
00169 }
00170 
00171 Socket::~Socket()
00172 {
00173         if (m_fd > 0)
00174         {
00175                 Close ();
00176         }
00177 }
00178 
00179 void Socket::SetNonBlocking()
00180 {
00181 #ifdef _WINDOWS
00182         u_long arg = 1;
00183         if (ioctlsocket(m_fd, FIONBIO, &arg) != 0)
00184         {
00185                 throw new SocketException(Environment::LastErrorMessage());
00186         }
00187 #else
00188         int flags;
00189 
00190         if ((flags = fcntl(m_fd, F_GETFL, 0)) < 0 ||
00191                         fcntl(m_fd, F_SETFL, flags | O_NONBLOCK) < 0)
00192         {
00193                 throw new SocketException(Environment::LastErrorMessage());
00194         }
00195 #endif
00196 }
00197 
00198 void Socket::SetBlocking()
00199 {
00200 #ifdef _WINDOWS
00201         u_long arg = 0;
00202         if (ioctlsocket(m_fd, FIONBIO, &arg) != 0)
00203         {
00204                 throw new SocketException(Environment::LastErrorMessage());
00205         }
00206 #else
00207         int flags;
00208 
00209         if ((flags = fcntl(m_fd, F_GETFL, 0)) < 0 ||
00210                         fcntl(m_fd, F_SETFL, flags & ~O_NONBLOCK) < 0)
00211         {
00212                 throw new SocketException(Environment::LastErrorMessage());
00213         }
00214 #endif
00215 }
00216 
00217 void ServerSocket::Bind ()
00218 {
00219         m_sock.m_saAddr.sin_addr.s_addr = htonl (INADDR_ANY);
00220 
00221         if (::bind (m_sock.m_fd, (struct sockaddr *)&m_sock.m_saAddr, sizeof (m_sock.m_saAddr)) != 0)
00222         {
00223                 m_sock.m_errorStatus = Environment::LastError();
00224                 throw new SocketException(Environment::LastErrorMessage());
00225         }
00226 }
00227 
00228 void Socket::SetNoDelay()
00229 {
00230 #ifdef _WINDOWS
00231         BOOL opt = TRUE;
00232         if (setsockopt(m_fd, IPPROTO_TCP, TCP_NODELAY, (const char FAR *)&opt, sizeof(BOOL)) != 0)
00233 #else
00234         int opt = 1;
00235         if (setsockopt(m_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, sizeof(int)) != 0)
00236 #endif
00237         {
00238                 throw new SocketException(Environment::LastErrorMessage());
00239         }
00240 }
00241 
00242 void Socket::SetSendTimeout(int toMS)
00243 {
00244         int ret = setsockopt(m_fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&toMS, sizeof(int));
00245 #ifdef _WINDOWS
00246         if ( ret != NO_ERROR )
00247 #else
00248         if ( ret < 0 )
00249 #endif
00250         {
00251                 throw new SocketException(Environment::LastErrorMessage());
00252         }
00253 }
00254 
00255 void Socket::SetRecvTimeout(int toMS)
00256 {
00257         int len = sizeof(int);
00258         int ret = setsockopt(m_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&toMS, sizeof(int));
00259 #ifdef _WIN32
00260         if ( ret != NO_ERROR )
00261 #else
00262         if ( ret < 0 )
00263 #endif
00264         {
00265                 throw new SocketException(Environment::LastErrorMessage());
00266         }
00267 }
00268 
00269 int Socket::GetSendTimeout()
00270 {
00271         int timeout;
00272 #ifdef _WIN32
00273         int len = sizeof(int);
00274 #else
00275         socklen_t len = sizeof(socklen_t);
00276 #endif
00277         int ret = getsockopt(m_fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, &len);
00278 #ifdef _WIN32
00279         if ( ret != NO_ERROR )
00280 #else
00281         if ( ret < 0 )
00282 #endif
00283         {
00284                 throw new SocketException(Environment::LastErrorMessage());
00285         }
00286         return timeout;
00287 }
00288 
00289 int Socket::GetRecvTimeout()
00290 {
00291         int timeout;
00292 #ifdef _WIN32
00293         int len = sizeof(int);
00294 #else
00295         socklen_t len = sizeof(socklen_t);
00296 #endif
00297         int ret = getsockopt(m_fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, &len);
00298 #ifdef _WIN32
00299         if ( ret != NO_ERROR )
00300 #else
00301         if ( ret < 0 )
00302 #endif
00303         {
00304                 throw new SocketException(Environment::LastErrorMessage());
00305         }
00306         return timeout;
00307 }
00308 
00309 void Socket::Flush()
00310 {
00311 #ifdef _WIN32
00312         int ret = WSAIoctl(m_fd, SIO_FLUSH, NULL, 0, NULL, 0, NULL, NULL, NULL);
00313         if ( ret != 0 )
00314         {
00315 #ifdef _WIN32
00316                 m_errorStatus = WSAGetLastError();
00317 #else
00318                 m_errorStatus = errno;
00319 #endif
00320                 throw new SocketException(Environment::LastErrorMessage());
00321         }
00322 #endif /* _WIN32 */
00323 }
00324 
00325 void Socket::SetAddrReuse (int i)
00326 {
00327         m_errorStatus = setsockopt (m_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&i, sizeof(int));
00328         if(m_errorStatus != 0)
00329         {
00330                 throw new SocketException(Environment::LastErrorMessage());
00331         }
00332 }
00333 
00334 void Socket::SetLingerOn ()
00335 {
00336         struct linger l;
00337 
00338         l.l_onoff = 1;
00339         l.l_linger = 5;
00340         if (setsockopt (m_fd, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(struct linger)) != 0)
00341         {
00342                 throw new SocketException(Environment::LastErrorMessage());
00343         }
00344 }
00345 
00346 void Socket::SetLingerOff ()
00347 {
00348         struct linger l;
00349 
00350         l.l_onoff = 0;
00351         l.l_linger = 0;
00352         if (setsockopt (m_fd, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(struct linger)) != 0)
00353         {
00354                 throw new SocketException(Environment::LastErrorMessage());
00355         }
00356 }
00357 
00358 void Socket::Send (const Array<byte>& data, const int offset, const int len)
00359 {
00360         ASSERT(offset + len <= data.Length());
00361 
00362         if (::send (m_fd, &(((const char *)data.Data())[offset]), len, 0) < 0)
00363         {
00364 #ifdef _WIN32
00365                 int err = WSAGetLastError();
00366 #else
00367                 int err = errno;
00368 #endif
00369                 m_errorStatus = err;
00370                 throw new SocketException(Environment::LastErrorMessage());
00371         }
00372 }
00373 
00374 int Socket::Recv (Array<byte>& buf, const int offset, const int blen)
00375 {
00376         ASSERT(offset + blen <= buf.Length());
00377 
00378         int count = ::recv (m_fd, &(((char *)buf.Data())[offset]), blen, 0);
00379 #ifdef _WIN32
00380         if ( SOCKET_ERROR == count )
00381 #else
00382         if ( 0 > count )
00383 #endif
00384         {
00385 #ifdef _WIN32
00386                 int err = WSAGetLastError();
00387 #else
00388                 int err = errno;
00389 #endif
00390                 m_errorStatus = err;
00391                 throw new SocketException(Environment::LastErrorMessage());
00392         }
00393         return count;
00394 }
00395 
00396 int Socket::RecvByte()
00397 {
00398         int b = 0;
00399         int count = ::recv (m_fd, (char *)&b, 1, 0);
00400 #ifdef _WIN32
00401         if ( SOCKET_ERROR == count )
00402 #else
00403         if ( 0 > count )
00404 #endif
00405         {
00406 #ifdef _WIN32
00407                 int err = WSAGetLastError();
00408 #else
00409                 int err = errno;
00410 #endif
00411                 m_errorStatus = err;
00412                 throw new SocketException(Environment::LastErrorMessage());
00413         }
00414         return b;
00415 }
00416 
00417 void ServerSocket::Listen (int iNumBuf)
00418 {
00419         if (::listen(m_sock.m_fd, iNumBuf) != 0)
00420         {
00421 #ifdef _WIN32
00422                 int error = WSAGetLastError();
00423 #else
00424                 int error = errno;
00425 #endif
00426                 throw new SocketException(Environment::LastErrorMessage());
00427         }
00428 }
00429 
00430 int Socket::GetBytesAvail(  )
00431 {
00432 #ifdef _WIN32
00433         u_long arg = 0;
00434         if (ioctlsocket(m_fd, FIONREAD, &arg) == 0)
00435         {
00436                 return (int)arg;
00437         }
00438         else
00439         {
00440                 m_errorStatus = WSAGetLastError();
00441                 throw new SocketException(Environment::LastErrorMessage());
00442         }
00443 #else
00444         int arg = 0;
00445         if ( ioctl(m_fd, FIONREAD, &arg) != 0 )
00446         {
00447                 m_errorStatus = errno;
00448                 throw new SocketException(Environment::LastErrorMessage());
00449         }
00450         return arg;
00451 #endif
00452 }
00453 
00454 String Socket::GetRemoteIp(  )
00455 {
00456         SOCKADDR_IN name;
00457         char buf[17];
00458 
00459 #ifdef _WIN32
00460         int namelen = sizeof(name);
00461 #else
00462         socklen_t namelen = sizeof(name);
00463 #endif
00464         if (0 != getpeername( m_fd, (struct sockaddr *)&name, &namelen ))
00465         {
00466                 throw new SocketException(Environment::LastErrorMessage());
00467         }
00468 #ifdef _WIN32
00469         sprintf(buf, "%hd.%hd.%hd.%hd", (short)name.sin_addr.S_un.S_un_b.s_b1, (short)name.sin_addr.S_un.S_un_b.s_b2, (short)name.sin_addr.S_un.S_un_b.s_b3, (short)name.sin_addr.S_un.S_un_b.s_b4);
00470 #else
00471         strcpy(buf, inet_ntoa(name.sin_addr));
00472 #endif
00473         return String(buf);
00474 }
00475 
00476 bool Socket::IsClosed() 
00477 { 
00478         // This doesn't always work
00479 
00480         if ( m_closed )
00481         {
00482                 return true;
00483         }
00484         char buf;
00485         int count = recv(m_fd, &buf, 1, MSG_PEEK);
00486         if ( 0 > count )
00487         {
00488                 m_closed = true;
00489                 return true;
00490         }
00491         
00492         return false;
00493 }
00494 
00495 void Socket::Shutdown( int i ) 
00496 {
00497         m_closed = true; 
00498         if ( 0 != ::shutdown(m_fd, i) )
00499         {
00500 #ifdef _WIN32
00501                 int error = WSAGetLastError();
00502 #else
00503                 int error = errno;
00504 #endif
00505                 m_errorStatus = error;
00506                 throw new SocketException(Environment::LastErrorMessage());
00507         }
00508 }
00509 
00510 void Socket::ShutdownService()
00511 {
00512 #ifdef _WIN32
00513         WSACleanup();
00514 #endif
00515 }
00516 
00517 #if defined(DEBUG) || defined(_DEBUG)
00518 void Socket::CheckMem() const
00519 {
00520 }
00521 
00522 void Socket::ValidateMem() const
00523 {
00524 }
00525 #endif
00526 
00527 
00528 ServerSocket::ServerSocket( int port, int numbuf )
00529 : m_sock(port)
00530 {
00531         Bind();
00532         Listen( numbuf );
00533 }
00534 
00535 ServerSocket::~ServerSocket()
00536 {
00537 }
00538 
00539 SocketStream::SocketStream(SocketPtr sock)
00540 : m_sock(sock)
00541 {
00542 }
00543 
00544 SocketStream::~SocketStream()
00545 {
00546         Close();
00547 }
00548 
00549 void SocketStream::Close()
00550 {
00551         m_sock->Close();
00552 }
00553 
00554 void SocketStream::Flush()
00555 {
00556         m_sock->Flush();
00557 }
00558 
00559 int SocketStream::Read(Array<byte>& buffer, const int offset, int count)
00560 {
00561         return m_sock->Recv(buffer, offset, count);
00562 }
00563 
00564 int SocketStream::ReadByte()
00565 {
00566         return m_sock->RecvByte();
00567 }
00568 
00569 long SocketStream::Seek(const long offset, const SeekOrigin origin)
00570 {
00571         throw new NotImplementedException();
00572 }
00573 
00574 void SocketStream::Write(const Array<byte>& buffer, const int offset, const int count)
00575 {
00576         m_sock->Send(buffer, offset, count);
00577 }
00578 
00579 void SocketStream::WriteByte(byte value)
00580 {
00581         Array<byte> buf(1);
00582         buf[0] = value;
00583         m_sock->Send(buf);
00584 }
00585 
00586 bool SocketStream::CanRead() const
00587 {
00588         return true;
00589 }
00590 
00591 bool SocketStream::CanSeek() const
00592 {
00593         return false;
00594 }
00595 
00596 bool SocketStream::CanWrite() const
00597 {
00598         return true;
00599 }
00600 
00601 long SocketStream::Length() const
00602 {
00603         return m_sock->GetBytesAvail();
00604 }
00605 
00606 long SocketStream::Position() const
00607 {
00608         return 0;
00609 }
00610 
00611 #ifdef DEBUG
00612 void SocketStream::ValidateMem() const
00613 {
00614         m_sock.ValidateMem();
00615 }
00616 
00617 void SocketStream::CheckMem() const
00618 {
00619         m_sock.CheckMem();
00620 }
00621 #endif
00622 
00623 TcpSocket::TcpSocket( SOCKET fd )
00624 : m_sock(new Socket(fd, false)), m_address("")
00625 {
00626         m_strm = SocketStreamPtr(new SocketStream(m_sock));
00627 }
00628 
00629 TcpSocket::TcpSocket( const String& address, int port )
00630 : m_sock(new Socket(port)), m_address(address)
00631 {
00632         m_strm = SocketStreamPtr(new SocketStream(m_sock));
00633 }
00634 
00635 TcpSocket::~TcpSocket()
00636 {
00637         m_sock->Close();
00638 }
00639 
00640 spl::IStreamPtr TcpSocket::GetStream()
00641 {
00642         return m_strm;
00643 }
00644 
00648 void TcpSocket::Connect ()
00649 {
00650         //addr.sin_family = AF_INET;
00651         //addr.sin_port = htons (port);         
00652 
00653         if (isdigit(m_address.CharAt(0)))
00654         {
00655                 m_sock->m_saAddr.sin_addr.s_addr = inet_addr(m_address.GetChars());
00656         }
00657         else
00658         {
00659                 hostent *phostent = gethostbyname(m_address.GetChars());
00660                 memcpy ((char *)&(m_sock->m_saAddr.sin_addr), phostent->h_addr, phostent->h_length);
00661         }
00662         if (::connect (m_sock->m_fd, (struct sockaddr *)&m_sock->m_saAddr, sizeof (SOCKADDR_IN)) != 0)
00663         {
00664                 m_sock->m_errorStatus = Environment::LastError();
00665                 throw new SocketException(Environment::LastErrorMessage());
00666         }
00667 }
00668 
00669 #if defined(DEBUG) || defined(_DEBUG)
00670 void TcpSocket::CheckMem() const 
00671 {
00672         m_strm.CheckMem(); 
00673         m_address.CheckMem(); 
00674         m_sock.CheckMem();
00675 }
00676 
00677 void TcpSocket::ValidateMem() const 
00678 {
00679         m_strm.ValidateMem(); 
00680         m_address.ValidateMem(); 
00681         m_sock.ValidateMem();
00682 }
00683 #endif