📄 sockets.cxx
字号:
return "tcp";
}
PBoolean PTCPSocket::Write(const void * buf, PINDEX len)
{
flush();
PINDEX writeCount = 0;
while (len > 0) {
if (!os_sendto(((char *)buf)+writeCount, len, 0, NULL, 0))
return PFalse;
writeCount += lastWriteCount;
len -= lastWriteCount;
}
lastWriteCount = writeCount;
return PTrue;
}
PBoolean PTCPSocket::Listen(unsigned queueSize, WORD newPort, Reusability reuse)
{
#if P_HAS_IPV6
return Listen(GetDefaultIpAny(), queueSize, newPort, reuse);
#else
return Listen(INADDR_ANY, queueSize, newPort, reuse);
#endif
}
PBoolean PTCPSocket::Listen(const Address & bindAddr,
unsigned queueSize,
WORD newPort,
Reusability reuse)
{
if (PIPSocket::Listen(bindAddr, queueSize, newPort, reuse) &&
ConvertOSError(::listen(os_handle, queueSize)))
return PTrue;
os_close();
return PFalse;
}
PBoolean PTCPSocket::Accept(PSocket & socket)
{
PAssert(PIsDescendant(&socket, PIPSocket), "Invalid listener socket");
#if P_HAS_IPV6
Psockaddr sa;
PINDEX size = sa.GetSize();
if (!os_accept(socket, sa, &size))
return PFalse;
#else
sockaddr_in address;
address.sin_family = AF_INET;
PINDEX size = sizeof(address);
if (!os_accept(socket, (struct sockaddr *)&address, &size))
return PFalse;
#endif
port = ((PIPSocket &)socket).GetPort();
return PTrue;
}
PBoolean PTCPSocket::WriteOutOfBand(void const * buf, PINDEX len)
{
#ifdef __NUCLEUS_NET__
PAssertAlways("WriteOutOfBand unavailable on Nucleus Plus");
//int count = NU_Send(os_handle, (char *)buf, len, 0);
int count = ::send(os_handle, (const char *)buf, len, 0);
#elif defined(P_VXWORKS)
int count = ::send(os_handle, (char *)buf, len, MSG_OOB);
#else
int count = ::send(os_handle, (const char *)buf, len, MSG_OOB);
#endif
if (count < 0) {
lastWriteCount = 0;
return ConvertOSError(count, LastWriteError);
}
else {
lastWriteCount = count;
return PTrue;
}
}
void PTCPSocket::OnOutOfBand(const void *, PINDEX)
{
}
//////////////////////////////////////////////////////////////////////////////
// PIPDatagramSocket
PIPDatagramSocket::PIPDatagramSocket()
{
}
PBoolean PIPDatagramSocket::ReadFrom(void * buf, PINDEX len,
Address & addr, WORD & port)
{
lastReadCount = 0;
#if P_HAS_IPV6
Psockaddr sa;
PINDEX size = sa.GetSize();
if (os_recvfrom(buf, len, 0, sa, &size)) {
addr = sa.GetIP();
port = sa.GetPort();
}
#else
sockaddr_in sockAddr;
PINDEX addrLen = sizeof(sockAddr);
if (os_recvfrom(buf, len, 0, (struct sockaddr *)&sockAddr, &addrLen)) {
addr = sockAddr.sin_addr;
port = ntohs(sockAddr.sin_port);
}
#endif
return lastReadCount > 0;
}
PBoolean PIPDatagramSocket::WriteTo(const void * buf, PINDEX len,
const Address & addr, WORD port)
{
lastWriteCount = 0;
PBoolean broadcast = addr.IsAny() || addr.IsBroadcast();
if (broadcast) {
#ifdef __BEOS__
PAssertAlways("Broadcast option under BeOS is not implemented yet");
return PFalse;
#else
if (!SetOption(SO_BROADCAST, 1))
return PFalse;
#endif
}
#if P_HAS_IPV6
Psockaddr sa(broadcast ? Address::GetBroadcast() : addr, port);
PBoolean ok = os_sendto(buf, len, 0, sa, sa.GetSize()) != 0;
#else
sockaddr_in sockAddr;
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr = (broadcast ? Address::GetBroadcast() : addr);
sockAddr.sin_port = htons(port);
PBoolean ok = os_sendto(buf, len, 0, (struct sockaddr *)&sockAddr, sizeof(sockAddr)) != 0;
#endif
#ifndef __BEOS__
if (broadcast)
SetOption(SO_BROADCAST, 0);
#endif
return ok && lastWriteCount >= len;
}
//////////////////////////////////////////////////////////////////////////////
// PUDPSocket
PUDPSocket::PUDPSocket(WORD newPort)
{
sendPort = 0;
SetPort(newPort);
OpenSocket();
}
PUDPSocket::PUDPSocket(PQoS * qos, WORD newPort)
{
if (qos != NULL)
qosSpec = *qos;
sendPort = 0;
SetPort(newPort);
OpenSocket();
}
PUDPSocket::PUDPSocket(const PString & service, PQoS * qos)
{
if (qos != NULL)
qosSpec = *qos;
sendPort = 0;
SetPort(service);
OpenSocket();
}
PUDPSocket::PUDPSocket(const PString & address, WORD newPort)
{
sendPort = 0;
SetPort(newPort);
Connect(address);
}
PUDPSocket::PUDPSocket(const PString & address, const PString & service)
{
sendPort = 0;
SetPort(service);
Connect(address);
}
PBoolean PUDPSocket::ModifyQoSSpec(PQoS * qos)
{
if (qos==NULL)
return PFalse;
qosSpec = *qos;
return PTrue;
}
#if P_HAS_QOS
PQoS & PUDPSocket::GetQoSSpec()
{
return qosSpec;
}
#endif
PBoolean PUDPSocket::ApplyQoS()
{
#ifdef _WIN32_WCE
return PFalse; //QoS not supported
#endif
char DSCPval = 0;
if (qosSpec.GetDSCP() < 0 ||
qosSpec.GetDSCP() > 63) {
if (qosSpec.GetServiceType() == SERVICETYPE_PNOTDEFINED)
return PTrue;
else {
switch (qosSpec.GetServiceType()) {
case SERVICETYPE_GUARANTEED:
DSCPval = PQoS::guaranteedDSCP;
break;
case SERVICETYPE_CONTROLLEDLOAD:
DSCPval = PQoS::controlledLoadDSCP;
break;
case SERVICETYPE_BESTEFFORT:
default:
DSCPval = PQoS::bestEffortDSCP;
break;
}
}
}
else
DSCPval = (char)qosSpec.GetDSCP();
#ifdef _WIN32
#if P_HAS_QOS
if (disableGQoS)
return PFalse;
PBoolean usesetsockopt = PFalse;
OSVERSIONINFO versInfo;
ZeroMemory(&versInfo,sizeof(OSVERSIONINFO));
versInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (!(GetVersionEx(&versInfo)))
usesetsockopt = PTrue;
else {
if (versInfo.dwMajorVersion < 5)
usesetsockopt = PTrue;
if (disableGQoS)
return PFalse;
PBoolean usesetsockopt = PFalse;
if (versInfo.dwMajorVersion == 5 &&
versInfo.dwMinorVersion == 0)
usesetsockopt = PTrue; //Windows 2000 does not always support QOS_DESTADDR
}
PBoolean retval = PFalse;
if (!usesetsockopt && sendAddress.IsValid() && sendPort != 0) {
sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = htons(sendPort);
sa.sin_addr = sendAddress;
memset(sa.sin_zero,0,8);
char * inBuf = new char[2048];
memset(inBuf,0,2048);
DWORD bufLen = 0;
PWinQoS wqos(qosSpec, (struct sockaddr *)(&sa), inBuf, bufLen);
DWORD dummy = 0;
int irval = WSAIoctl(os_handle, SIO_SET_QOS, inBuf, bufLen, NULL, 0, &dummy, NULL, NULL);
delete[] inBuf;
return irval == 0;
}
if (!usesetsockopt)
return retval;
#endif // P_HAS_QOS
#endif // _WIN32
unsigned int setDSCP = DSCPval<<2;
int rv = 0;
unsigned int curval = 0;
socklen_t cursize = sizeof(curval);
rv = ::getsockopt(os_handle,IPPROTO_IP, IP_TOS, (char *)(&curval), &cursize);
if (curval == setDSCP)
return PTrue; //Required DSCP already set
rv = ::setsockopt(os_handle, IPPROTO_IP, IP_TOS, (char *)&setDSCP, sizeof(setDSCP));
if (rv != 0) {
int err;
#ifdef _WIN32
err = WSAGetLastError();
#else
err = errno;
#endif
PTRACE(1,"QOS\tsetsockopt failed with code " << err);
return PFalse;
}
return PTrue;
}
PBoolean PUDPSocket::OpenSocketGQOS(int af, int type, int proto)
{
#ifdef _WIN32_WCE //QOS not supported
return ConvertOSError(os_handle = os_socket(af, type, proto));
#endif
#if defined(_WIN32) && defined(P_HAS_QOS)
DWORD bufferSize = 0;
DWORD numProtocols, i;
LPWSAPROTOCOL_INFO installedProtocols, qosProtocol;
//Try to find a QOS-enabled protocol
PBoolean retval = ConvertOSError(numProtocols = WSAEnumProtocols(((proto==0) ? NULL : &proto),
NULL,
&bufferSize));
if (numProtocols == SOCKET_ERROR && WSAGetLastError()!=WSAENOBUFS)
return retval;
installedProtocols = (LPWSAPROTOCOL_INFO)(new BYTE[bufferSize]);
retval = ConvertOSError(numProtocols = WSAEnumProtocols(((proto==0) ? NULL : &proto),
installedProtocols,
&bufferSize));
if (numProtocols == SOCKET_ERROR) {
delete[] installedProtocols;
return retval;
}
qosProtocol = installedProtocols;
PBoolean haveQoSproto = PFalse;
for (i=0; i<numProtocols; qosProtocol++, i++) {
if ((qosProtocol->dwServiceFlags1 & XP1_QOS_SUPPORTED) &&
(qosProtocol->iSocketType == type) &&
(qosProtocol->iAddressFamily == af)) {
haveQoSproto = PTrue;
break;
}
}
if (haveQoSproto) {
retval = ConvertOSError(os_handle = WSASocket(af,
type,
proto,
qosProtocol,
0,
WSA_FLAG_OVERLAPPED));
}
else
{
retval = ConvertOSError(os_handle = WSASocket (af,
type,
proto,
NULL,
0,
WSA_FLAG_OVERLAPPED));
}
delete[] installedProtocols;
if (os_handle == INVALID_SOCKET)
return retval;
#else
PBoolean retval = ConvertOSError(os_handle = os_socket(af, type, proto));
#endif
return retval;
}
#ifdef _WIN32
#ifndef _WIN32_WCE
#ifdef P_HAS_QOS
#define COULD_HAVE_QOS
static PBoolean CheckOSVersion()
{
OSVERSIONINFO versInfo;
ZeroMemory(&versInfo,sizeof(OSVERSIONINFO));
versInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&versInfo))
{
if (versInfo.dwMajorVersion > 5 ||
(versInfo.dwMajorVersion == 5 &&
versInfo.dwMinorVersion > 0))
return PTrue;
}
return PFalse;
}
#endif
#endif
#endif
PBoolean PUDPSocket::OpenSocket()
{
#ifdef COULD_HAVE_QOS
if (CheckOSVersion())
return OpenSocketGQOS(AF_INET, SOCK_DGRAM, 0);
#endif
return ConvertOSError(os_handle = os_socket(AF_INET,SOCK_DGRAM, 0));
}
PBoolean PUDPSocket::OpenSocket(int ipAdressFamily)
{
#ifdef COULD_HAVE_QOS
if (CheckOSVersion())
return OpenSocketGQOS(ipAdressFamily, SOCK_DGRAM, 0);
#endif
return ConvertOSError(os_handle = os_socket(ipAdressFamily,SOCK_DGRAM, 0));
}
const char * PUDPSocket::GetProtocolName() const
{
return "udp";
}
PBoolean PUDPSocket::Connect(const PString & address)
{
sendPort = 0;
return PIPDatagramSocket::Connect(address);
}
PBoolean PUDPSocket::Read(void * buf, PINDEX len)
{
return PIPDatagramSocket::ReadFrom(buf, len, lastReceiveAddress, lastReceivePort);
}
PBoolean PUDPSocket::Write(const void * buf, PINDEX len)
{
if (sendPort == 0)
return PIPDatagramSocket::Write(buf, len);
else
return PIPDatagramSocket::WriteTo(buf, len, sendAddress, sendPort);
}
void PUDPSocket::SetSendAddress(const Address & newAddress, WORD newPort)
{
sendAddress = newAddress;
sendPort = newPort;
ApplyQoS();
}
void PUDPSocket::GetSendAddress(Address & address, WORD & port)
{
address = sendAddress;
port = sendPort;
}
void PUDPSocket::GetLastReceiveAddress(Address & address, WORD & port)
{
address = lastReceiveAddress;
port = lastReceivePort;
}
//////////////////////////////////////////////////////////////////////////////
PBoolean PICMPSocket::OpenSocket(int)
{
return PFalse;
}
//////////////////////////////////////////////////////////////////////////////
PBoolean PIPSocketAddressAndPort::Parse(const PString & str, WORD _port, char _sep)
{
sep = _sep;
port = _port;
PINDEX pos = str.Find(sep);
if (pos != P_MAX_INDEX) {
port = (WORD)str.Mid(pos+1).AsInteger();
if (!PIPSocket::GetHostAddress(str.Left(pos), address))
return PFalse;
}
else if (port == 0)
return PFalse;
else if (!PIPSocket::GetHostAddress(str, address))
return PFalse;
return PTrue;
}
// End Of File ///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -