📄 swisocket.cpp
字号:
/****************License************************************************
* Vocalocity OpenVXI
* Copyright (C) 2004-2005 by Vocalocity, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Vocalocity, the Vocalocity logo, and VocalOS are trademarks or
* registered trademarks of Vocalocity, Inc.
* OpenVXI is a trademark of Scansoft, Inc. and used under license
* by Vocalocity.
***********************************************************************/
#if _MSC_VER >= 1100 // Visual C++ 5.x
#pragma warning( disable : 4786 4503 )
#endif
#ifdef _WIN32
#include <winsock2.h>
#define WSA_LAST_ERROR WSAGetLastError()
#define WSA_ERROR_NAME L"WinsockError"
#else
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#ifdef _solaris_
#include <stropts.h>
#include <fcntl.h>
#include <string.h>
#endif
#define WSA_LAST_ERROR errno
#define WSA_ERROR_NAME L"errno"
#define WSAEADDRINUSE EADDRINUSE
#define WSAECONNABORTED ECONNABORTED
#define WSAECONNRESET ECONNRESET
#define WSAECONNREFUSED ECONNREFUSED
#define WSAEHOSTDOWN EHOSTDOWN
#define WSAEHOSTUNREACH EHOSTUNREACH
#define WSAEWOULDBLOCK EINPROGRESS
#define WSAEACCESS EACCESS
#define WSAENOTSOCK EBADF
#define WSAEINTR EINTR
#define closesocket close
#define ioctlsocket ioctl
#endif
#include "SWIsocket.hpp"
#include "SWIipAddress.hpp"
static timeval* millisecToTimeval(long millisec, timeval& tv)
{
if (millisec < 0)
{
tv.tv_sec = -1;
tv.tv_usec = -1;
return NULL;
}
tv.tv_sec = (millisec / 1000);
tv.tv_usec = (millisec % 1000) * 1000;
return &tv;
}
SWIsocket::SWIsocket(Type socktype,
SWIutilLogger *logger):
_logger(logger), _sd(INVALID_SOCKET),
_bound(false), _connected(false), _shutIn(false), _shutOut(false),
_remoteAddress(NULL), _localAddress(NULL), _rtmo(-1), _stmo(-1),
_inStream(NULL), _outStream(NULL)
{
_sd = socket(AF_INET, socktype, 0);
if (_sd == INVALID_SOCKET)
{
error(L"socket", 500, WSA_LAST_ERROR);
}
}
SWIsocket::SWIsocket(const SWIsocket *socket, SOCKET sd):
_logger(socket->_logger), _sd(sd), _bound(true), _connected(true),
_shutIn(false), _shutOut(false),
_remoteAddress(NULL), _localAddress(NULL),
_rtmo(socket->_rtmo), _stmo(socket->_stmo),
_inStream(NULL), _outStream(NULL)
{}
SWIsocket::~SWIsocket()
{
close();
if (_inStream != NULL)
{
_inStream->_sock = NULL;
}
if (_outStream != NULL)
{
_outStream->_sock = NULL;
}
delete _remoteAddress;
delete _localAddress;
}
SWIstream::Result SWIsocket::connect(const SWIipAddress& endpoint, long timeout)
{
SWIstream::Result rc = SWIstream::SUCCESS;
unsigned long nonblocking = 1;
int flags = 0;
timeval tv;
timeval *ptv = millisecToTimeval(timeout, tv);
if (ptv != NULL)
{
#ifdef _solaris_
flags = fcntl(_sd, F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl(_sd, F_SETFL, flags);
#else
ioctlsocket(_sd, FIONBIO, &nonblocking);
nonblocking = 0;
#endif
}
if (::connect(_sd, endpoint.addr(), endpoint.size()) != 0)
{
int wserr = WSA_LAST_ERROR;
if (wserr != WSAEWOULDBLOCK)
{
error(L"connect", 500, wserr);
rc = SWIstream::FAILURE;
goto cleanup;
}
}
if (ptv != NULL)
{
int status = is_writeready(ptv);
if (status == 0)
{
rc = SWIstream::TIMED_OUT;
goto cleanup;
}
if (status < 0)
{
rc = SWIstream::OPEN_ERROR;
goto cleanup;
}
}
_bound = _connected = true;
cleanup:
// restore blocking mode.
if (ptv != NULL)
{
#ifdef _solaris_
flags = fcntl(_sd, F_GETFL, 0);
flags &= ~O_NONBLOCK;
fcntl(_sd, F_SETFL, flags);
#else
ioctlsocket(_sd, FIONBIO, &nonblocking);
#endif
}
return rc;
}
SWIstream::Result SWIsocket::connect(const char *hostname, int port, long timeout)
{
SWIipAddress endpoint(hostname, port, _logger);
return connect(endpoint, timeout);
}
SWIstream::Result SWIsocket::connect(unsigned long addr, int port, long timeout)
{
SWIipAddress endpoint(addr, port, _logger);
return connect(endpoint, timeout);
}
SWIstream::Result SWIsocket::connect(unsigned long addr,
const char *service_name,
const char *protocol_name,
long timeout)
{
SWIipAddress endpoint(addr, service_name, protocol_name, _logger);
return connect(endpoint, timeout);
}
SWIstream::Result SWIsocket::connect(const char *host,
const char *service_name,
const char *protocol_name,
long timeout)
{
SWIipAddress endpoint(host, service_name, protocol_name, _logger);
return connect(endpoint, timeout);
}
SWIstream::Result SWIsocket::bind(const SWIipAddress& sa)
{
int rc = ::bind(_sd, sa.addr (), sa.size ());
if (rc != 0)
{
error(L"bind", 500, WSA_LAST_ERROR);
return SWIstream::FAILURE;
}
_bound = true;
return SWIstream::SUCCESS;
}
SWIstream::Result SWIsocket::bind()
{
SWIipAddress sa(_logger);
return bind(sa);
}
SWIstream::Result SWIsocket::bind(unsigned long addr, int port_no)
{
SWIipAddress sa(addr, port_no, _logger);
return bind(sa);
}
SWIstream::Result SWIsocket::bind(const char* host_name, int port_no)
{
SWIipAddress sa(host_name, port_no, _logger);
return bind (sa);
}
SWIstream::Result SWIsocket::bind(unsigned long addr,
const char* service_name,
const char* protocol_name)
{
SWIipAddress sa(addr, service_name, protocol_name, _logger);
return bind(sa);
}
SWIstream::Result SWIsocket::bind(const char* host_name,
const char* service_name,
const char* protocol_name)
{
SWIipAddress sa(host_name, service_name, protocol_name, _logger);
return bind(sa);
}
SWIstream::Result SWIsocket::listen(int backlog)
{
int rc = ::listen (_sd, backlog);
if (rc != 0)
{
error(L"listen", 500, WSA_LAST_ERROR);
return SWIstream::FAILURE;
}
return SWIstream::SUCCESS;
}
SWIsocket *SWIsocket::accept(SWIipAddress& sa)
{
int wserr;
socklen_t len = sa.size();
SOCKET soc = INVALID_SOCKET;
while ((soc = ::accept (_sd, sa.addr(), &len)) == INVALID_SOCKET
&& (wserr = WSA_LAST_ERROR) == WSAEINTR);
if (soc == INVALID_SOCKET)
{
error(L"accept", 500, wserr);
return NULL;
}
return new SWIsocket(this, soc);
}
SWIsocket* SWIsocket::accept()
{
int wserr;
SOCKET soc = INVALID_SOCKET;
while ((soc = ::accept (_sd, NULL, NULL)) == INVALID_SOCKET
&& (wserr = WSA_LAST_ERROR) == WSAEINTR);
if (soc == INVALID_SOCKET)
{
error(L"accept", 500, wserr);
return NULL;
}
return new SWIsocket(this, soc);
}
const SWIipAddress *SWIsocket::getRemoteAddress() const
{
// if (!_connected)
// return NULL;
if (_remoteAddress != NULL)
return _remoteAddress;
_remoteAddress = new SWIipAddress(_logger);
socklen_t len = _remoteAddress->size();
if (::getpeername(_sd, _remoteAddress->addr(), &len) != 0)
{
error(L"getpeername", 500, WSA_LAST_ERROR);
delete _remoteAddress;
_remoteAddress = NULL;
}
return _remoteAddress;
}
const SWIipAddress *SWIsocket::getLocalAddress() const
{
//if (!_bound)
//return NULL;
if (_localAddress != NULL)
return _localAddress;
_localAddress = new SWIipAddress(_logger);
socklen_t len = _localAddress->size();
if (::getsockname(_sd, _localAddress->addr(), &len) != 0)
{
error(L"getsockname", 500, WSA_LAST_ERROR);
delete _localAddress;
_localAddress = NULL;
}
return _localAddress;
}
int SWIsocket::getRemotePort() const
{
const SWIipAddress* addr = getRemoteAddress();
if (addr == NULL)
{
return 0;
}
else
return addr->getport();
}
int SWIsocket::getLocalPort() const
{
const SWIipAddress* addr = getLocalAddress();
if (addr == NULL)
{
return 0;
}
else
return addr->getport();
}
SWIstream::Result SWIsocket::close()
{
if (_sd != INVALID_SOCKET)
{
::closesocket(_sd);
_sd = INVALID_SOCKET;
}
return SWIstream::SUCCESS;
}
SWIinputStream *SWIsocket::getInputStream()
{
if (_inStream == NULL)
{
_inStream = new InputStream(this);
}
return _inStream;
}
SWIoutputStream *SWIsocket::getOutputStream()
{
if (_outStream == NULL)
{
_outStream = new OutputStream(this);
}
return _outStream;
}
SWIsocket::InputStream::InputStream(SWIsocket *sock):
_sock(sock)
{}
SWIsocket::InputStream::~InputStream()
{
if (_sock != NULL)
{
_sock->shutdown(shut_read);
_sock->_inStream = NULL;
}
}
int SWIsocket::InputStream::readBytes(void *data, int dataSize)
{
return _sock != NULL ? _sock->recv(data, dataSize) : SWIstream::ILLEGAL_STATE;
}
SWIstream::Result SWIsocket::InputStream::close()
{
if (_sock == NULL)
return SWIstream::ILLEGAL_STATE;
return _sock->shutdown(shut_read);
}
SWIstream::Result SWIsocket::InputStream::waitReady(long timeoutMs)
{
if (_sock == NULL)
return SWIstream::ILLEGAL_STATE;
switch (_sock->is_readready(timeoutMs))
{
case 1:
return SUCCESS;
case 0:
return TIMED_OUT;
default:
return FAILURE;
}
}
SWIsocket::OutputStream::OutputStream(SWIsocket *sock):
_sock(sock)
{}
SWIsocket::OutputStream::~OutputStream()
{
if (_sock != NULL)
{
_sock->shutdown(shut_write);
_sock->_outStream = NULL;
}
}
int SWIsocket::OutputStream::writeBytes(const void *buffer, int bufferSize)
{
return _sock != NULL ? _sock->send(buffer, bufferSize) : SWIstream::ILLEGAL_STATE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -