Add even more of the source
This should be about everything needed to build so far?
This commit is contained in:
parent
af3619d4fa
commit
849723c9cf
547 changed files with 149239 additions and 0 deletions
391
CommonUtilitiesLib/Socket.cpp
Normal file
391
CommonUtilitiesLib/Socket.cpp
Normal file
|
@ -0,0 +1,391 @@
|
|||
/*
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*
|
||||
*/
|
||||
/*
|
||||
File: Socket.cpp
|
||||
|
||||
Contains: implements Socket class
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifndef __Win32__
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "Socket.h"
|
||||
#include "SocketUtils.h"
|
||||
#include "OSMemory.h"
|
||||
|
||||
#ifdef USE_NETLOG
|
||||
#include <netlog.h>
|
||||
#else
|
||||
#if defined(__Win32__) || defined(__sgi__) || defined(__osf__) || defined(__hpux__)
|
||||
typedef int socklen_t; // missing from some platform includes
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
EventThread* Socket::sEventThread = NULL;
|
||||
|
||||
Socket::Socket(Task *notifytask, UInt32 inSocketType)
|
||||
: EventContext(EventContext::kInvalidFileDesc, sEventThread),
|
||||
fState(inSocketType),
|
||||
fLocalAddrStrPtr(NULL),
|
||||
fLocalDNSStrPtr(NULL),
|
||||
fPortStr(fPortBuffer, kPortBufSizeInBytes)
|
||||
{
|
||||
fLocalAddr.sin_addr.s_addr = 0;
|
||||
fLocalAddr.sin_port = 0;
|
||||
|
||||
fDestAddr.sin_addr.s_addr = 0;
|
||||
fDestAddr.sin_port = 0;
|
||||
|
||||
this->SetTask(notifytask);
|
||||
|
||||
#if SOCKET_DEBUG
|
||||
fLocalAddrStr.Set(fLocalAddrBuffer,sizeof(fLocalAddrBuffer));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
OS_Error Socket::Open(int theType)
|
||||
{
|
||||
Assert(fFileDesc == EventContext::kInvalidFileDesc);
|
||||
fFileDesc = ::socket(PF_INET, theType, 0);
|
||||
if (fFileDesc == EventContext::kInvalidFileDesc)
|
||||
return (OS_Error)OSThread::GetErrno();
|
||||
|
||||
//
|
||||
// Setup this socket's event context
|
||||
if (fState & kNonBlockingSocketType)
|
||||
this->InitNonBlocking(fFileDesc);
|
||||
|
||||
return OS_NoErr;
|
||||
}
|
||||
|
||||
void Socket::ReuseAddr()
|
||||
{
|
||||
int one = 1;
|
||||
int err = ::setsockopt(fFileDesc, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(int));
|
||||
Assert(err == 0);
|
||||
}
|
||||
|
||||
void Socket::NoDelay()
|
||||
{
|
||||
int one = 1;
|
||||
int err = ::setsockopt(fFileDesc, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(int));
|
||||
Assert(err == 0);
|
||||
}
|
||||
|
||||
void Socket::KeepAlive()
|
||||
{
|
||||
int one = 1;
|
||||
int err = ::setsockopt(fFileDesc, SOL_SOCKET, SO_KEEPALIVE, (char*)&one, sizeof(int));
|
||||
Assert(err == 0);
|
||||
}
|
||||
|
||||
void Socket::SetSocketBufSize(UInt32 inNewSize)
|
||||
{
|
||||
|
||||
#if SOCKET_DEBUG
|
||||
int value;
|
||||
int buffSize = sizeof(value);
|
||||
int error = ::getsockopt(fFileDesc, SOL_SOCKET, SO_SNDBUF, (void*)&value, (socklen_t*)&buffSize);
|
||||
#endif
|
||||
|
||||
int bufSize = inNewSize;
|
||||
int err = ::setsockopt(fFileDesc, SOL_SOCKET, SO_SNDBUF, (char*)&bufSize, sizeof(int));
|
||||
AssertV(err == 0, OSThread::GetErrno());
|
||||
|
||||
#if SOCKET_DEBUG
|
||||
int setValue;
|
||||
error = ::getsockopt(fFileDesc, SOL_SOCKET, SO_SNDBUF, (void*)&setValue, (socklen_t*)&buffSize);
|
||||
qtss_printf("Socket::SetSocketBufSize ");
|
||||
if (fState & kBound)
|
||||
{ if (NULL != this->GetLocalAddrStr())
|
||||
this->GetLocalAddrStr()->PrintStr(":");
|
||||
if (NULL != this->GetLocalPortStr())
|
||||
this->GetLocalPortStr()->PrintStr(" ");
|
||||
}
|
||||
else
|
||||
qtss_printf("unbound ");
|
||||
qtss_printf("socket=%d old SO_SNDBUF =%d inNewSize=%d setValue=%d\n", (int) fFileDesc, value, bufSize, setValue);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
OS_Error Socket::SetSocketRcvBufSize(UInt32 inNewSize)
|
||||
{
|
||||
#if SOCKET_DEBUG
|
||||
int value;
|
||||
int buffSize = sizeof(value);
|
||||
int error = ::getsockopt(fFileDesc, SOL_SOCKET, SO_RCVBUF, (void*)&value, (socklen_t*)&buffSize);
|
||||
#endif
|
||||
|
||||
int bufSize = inNewSize;
|
||||
int err = ::setsockopt(fFileDesc, SOL_SOCKET, SO_RCVBUF, (char*)&bufSize, sizeof(int));
|
||||
|
||||
#if SOCKET_DEBUG
|
||||
int setValue;
|
||||
error = ::getsockopt(fFileDesc, SOL_SOCKET, SO_RCVBUF, (void*)&setValue, (socklen_t*)&buffSize);
|
||||
qtss_printf("Socket::SetSocketRcvBufSize ");
|
||||
if (fState & kBound)
|
||||
{ if (NULL != this->GetLocalAddrStr())
|
||||
this->GetLocalAddrStr()->PrintStr(":");
|
||||
if (NULL != this->GetLocalPortStr())
|
||||
this->GetLocalPortStr()->PrintStr(" ");
|
||||
}
|
||||
else
|
||||
qtss_printf("unbound ");
|
||||
qtss_printf("socket=%d old SO_RCVBUF =%d inNewSize=%d setValue=%d\n",(int) fFileDesc, value, bufSize, setValue);
|
||||
#endif
|
||||
|
||||
|
||||
if (err == -1)
|
||||
return OSThread::GetErrno();
|
||||
|
||||
return OS_NoErr;
|
||||
}
|
||||
|
||||
|
||||
OS_Error Socket::Bind(UInt32 addr, UInt16 port, UInt16 test)
|
||||
{
|
||||
socklen_t len = sizeof(fLocalAddr);
|
||||
::memset(&fLocalAddr, 0, sizeof(fLocalAddr));
|
||||
fLocalAddr.sin_family = AF_INET;
|
||||
fLocalAddr.sin_port = htons(port);
|
||||
fLocalAddr.sin_addr.s_addr = htonl(addr);
|
||||
|
||||
int err;
|
||||
|
||||
#if 0
|
||||
if (test) // pick some ports or conditions to return an error on.
|
||||
{
|
||||
if (6971 == port)
|
||||
{
|
||||
fLocalAddr.sin_port = 0;
|
||||
fLocalAddr.sin_addr.s_addr = 0;
|
||||
return EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
err = ::bind(fFileDesc, (sockaddr *)&fLocalAddr, sizeof(fLocalAddr));
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
err = ::bind(fFileDesc, (sockaddr *)&fLocalAddr, sizeof(fLocalAddr));
|
||||
|
||||
|
||||
if (err == -1)
|
||||
{
|
||||
fLocalAddr.sin_port = 0;
|
||||
fLocalAddr.sin_addr.s_addr = 0;
|
||||
return (OS_Error)OSThread::GetErrno();
|
||||
}
|
||||
else ::getsockname(fFileDesc, (sockaddr *)&fLocalAddr, &len); // get the kernel to fill in unspecified values
|
||||
fState |= kBound;
|
||||
return OS_NoErr;
|
||||
}
|
||||
|
||||
StrPtrLen* Socket::GetLocalAddrStr()
|
||||
{
|
||||
//Use the array of IP addr strings to locate the string formatted version
|
||||
//of this IP address.
|
||||
if (fLocalAddrStrPtr == NULL)
|
||||
{
|
||||
for (UInt32 x = 0; x < SocketUtils::GetNumIPAddrs(); x++)
|
||||
{
|
||||
if (SocketUtils::GetIPAddr(x) == ntohl(fLocalAddr.sin_addr.s_addr))
|
||||
{
|
||||
fLocalAddrStrPtr = SocketUtils::GetIPAddrStr(x);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if SOCKET_DEBUG
|
||||
if (fLocalAddrStrPtr == NULL)
|
||||
{ // shouldn't happen but no match so it was probably a failed socket connection or accept. addr is probably 0.
|
||||
|
||||
fLocalAddrBuffer[0]=0;
|
||||
fLocalAddrStrPtr = &fLocalAddrStr;
|
||||
struct in_addr theAddr;
|
||||
theAddr.s_addr =ntohl(fLocalAddr.sin_addr.s_addr);
|
||||
SocketUtils::ConvertAddrToString(theAddr, &fLocalAddrStr);
|
||||
|
||||
printf("Socket::GetLocalAddrStr Search IPs failed, numIPs=%d\n",SocketUtils::GetNumIPAddrs());
|
||||
for (UInt32 x = 0; x < SocketUtils::GetNumIPAddrs(); x++)
|
||||
{ printf("ip[%"_U32BITARG_"]=",x); SocketUtils::GetIPAddrStr(x)->PrintStr("\n");
|
||||
}
|
||||
printf("this ip = %d = ",theAddr.s_addr); fLocalAddrStrPtr->PrintStr("\n");
|
||||
|
||||
if (theAddr.s_addr == 0 || fLocalAddrBuffer[0] == 0)
|
||||
fLocalAddrStrPtr = NULL; // so the caller can test for failure
|
||||
}
|
||||
#endif
|
||||
|
||||
Assert(fLocalAddrStrPtr != NULL);
|
||||
return fLocalAddrStrPtr;
|
||||
}
|
||||
|
||||
StrPtrLen* Socket::GetLocalDNSStr()
|
||||
{
|
||||
//Do the same thing as the above function, but for DNS names
|
||||
Assert(fLocalAddr.sin_addr.s_addr != INADDR_ANY);
|
||||
if (fLocalDNSStrPtr == NULL)
|
||||
{
|
||||
for (UInt32 x = 0; x < SocketUtils::GetNumIPAddrs(); x++)
|
||||
{
|
||||
if (SocketUtils::GetIPAddr(x) == ntohl(fLocalAddr.sin_addr.s_addr))
|
||||
{
|
||||
fLocalDNSStrPtr = SocketUtils::GetDNSNameStr(x);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if we weren't able to get this DNS name, make the DNS name the same as the IP addr str.
|
||||
if (fLocalDNSStrPtr == NULL)
|
||||
fLocalDNSStrPtr = this->GetLocalAddrStr();
|
||||
|
||||
Assert(fLocalDNSStrPtr != NULL);
|
||||
return fLocalDNSStrPtr;
|
||||
}
|
||||
|
||||
StrPtrLen* Socket::GetLocalPortStr()
|
||||
{
|
||||
if (fPortStr.Len == kPortBufSizeInBytes)
|
||||
{
|
||||
int temp = ntohs(fLocalAddr.sin_port);
|
||||
qtss_sprintf(fPortBuffer, "%d", temp);
|
||||
fPortStr.Len = ::strlen(fPortBuffer);
|
||||
}
|
||||
return &fPortStr;
|
||||
}
|
||||
|
||||
OS_Error Socket::Send(const char* inData, const UInt32 inLength, UInt32* outLengthSent)
|
||||
{
|
||||
Assert(inData != NULL);
|
||||
|
||||
if (!(fState & kConnected))
|
||||
return (OS_Error)ENOTCONN;
|
||||
|
||||
int err;
|
||||
do {
|
||||
err = ::send(fFileDesc, inData, inLength, 0);//flags??
|
||||
} while((err == -1) && (OSThread::GetErrno() == EINTR));
|
||||
if (err == -1)
|
||||
{
|
||||
//Are there any errors that can happen if the client is connected?
|
||||
//Yes... EAGAIN. Means the socket is now flow-controleld
|
||||
int theErr = OSThread::GetErrno();
|
||||
if ((theErr != EAGAIN) && (this->IsConnected()))
|
||||
fState ^= kConnected;//turn off connected state flag
|
||||
return (OS_Error)theErr;
|
||||
}
|
||||
|
||||
*outLengthSent = err;
|
||||
return OS_NoErr;
|
||||
}
|
||||
|
||||
OS_Error Socket::WriteV(const struct iovec* iov, const UInt32 numIOvecs, UInt32* outLenSent)
|
||||
{
|
||||
Assert(iov != NULL);
|
||||
|
||||
if (!(fState & kConnected))
|
||||
return (OS_Error)ENOTCONN;
|
||||
|
||||
int err;
|
||||
do {
|
||||
#ifdef __Win32__
|
||||
DWORD theBytesSent = 0;
|
||||
err = ::WSASend(fFileDesc, (LPWSABUF)iov, numIOvecs, &theBytesSent, 0, NULL, NULL);
|
||||
if (err == 0)
|
||||
err = theBytesSent;
|
||||
#else
|
||||
err = ::writev(fFileDesc, iov, numIOvecs);//flags??
|
||||
#endif
|
||||
} while((err == -1) && (OSThread::GetErrno() == EINTR));
|
||||
if (err == -1)
|
||||
{
|
||||
// Are there any errors that can happen if the client is connected?
|
||||
// Yes... EAGAIN. Means the socket is now flow-controleld
|
||||
int theErr = OSThread::GetErrno();
|
||||
if ((theErr != EAGAIN) && (this->IsConnected()))
|
||||
fState ^= kConnected;//turn off connected state flag
|
||||
return (OS_Error)theErr;
|
||||
}
|
||||
if (outLenSent != NULL)
|
||||
*outLenSent = (UInt32)err;
|
||||
|
||||
return OS_NoErr;
|
||||
}
|
||||
|
||||
OS_Error Socket::Read(void *buffer, const UInt32 length, UInt32 *outRecvLenP)
|
||||
{
|
||||
Assert(outRecvLenP != NULL);
|
||||
Assert(buffer != NULL);
|
||||
|
||||
if (!(fState & kConnected))
|
||||
return (OS_Error)ENOTCONN;
|
||||
|
||||
//int theRecvLen = ::recv(fFileDesc, buffer, length, 0);//flags??
|
||||
int theRecvLen;
|
||||
do {
|
||||
theRecvLen = ::recv(fFileDesc, (char*)buffer, length, 0);//flags??
|
||||
} while((theRecvLen == -1) && (OSThread::GetErrno() == EINTR));
|
||||
|
||||
if (theRecvLen == -1)
|
||||
{
|
||||
// Are there any errors that can happen if the client is connected?
|
||||
// Yes... EAGAIN. Means the socket is now flow-controleld
|
||||
int theErr = OSThread::GetErrno();
|
||||
if ((theErr != EAGAIN) && (this->IsConnected()))
|
||||
fState ^= kConnected;//turn off connected state flag
|
||||
return (OS_Error)theErr;
|
||||
}
|
||||
//if we get 0 bytes back from read, that means the client has disconnected.
|
||||
//Note that and return the proper error to the caller
|
||||
else if (theRecvLen == 0)
|
||||
{
|
||||
fState ^= kConnected;
|
||||
return (OS_Error)ENOTCONN;
|
||||
}
|
||||
Assert(theRecvLen > 0);
|
||||
*outRecvLenP = (UInt32)theRecvLen;
|
||||
return OS_NoErr;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue