Exemplo n.º 1
0
int CUDTUnited::bind(const UDTSOCKET u, const UDPSOCKET* udpsaock, const sockaddr* name, int namelen)
{
	CUDTSocket* s = locate(u);
	if (NULL == s)
		throw CUDTException(5, 4, 0);

	CGuard cg(s->m_ControlLock);

	// cannot bind a socket more than once
	if (INIT != s->m_Status)
		throw CUDTException(5, 0, 0);

	// check the size of SOCKADDR structure
	if (AF_INET == s->m_iIPversion)
	{
		if (namelen != sizeof(sockaddr_in))
			throw CUDTException(5, 3, 0);
	}
	else
	{
		if (namelen != sizeof(sockaddr_in6))
			throw CUDTException(5, 3, 0);
	}

	s->m_pUDT->open();
	updateMux(s, name, udpsaock);
	s->m_Status = OPENED;

	// copy address information of local node
	s->m_pUDT->m_pSndQueue->m_pChannel->getSockAddr(s->m_pSelfAddr);

	return 0;
}
Exemplo n.º 2
0
void CChannel::setUDPSockOpt()
{
   if ((0 != setsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char *)&m_iRcvBufSize, sizeof(int))) ||
       (0 != setsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char *)&m_iSndBufSize, sizeof(int))))
      throw CUDTException(1, 3, NET_ERROR);

   timeval tv;
   tv.tv_sec = 0;
   #if defined (BSD) || defined (OSX)
      // Known BSD bug as the day I wrote this code.
      // A small time out value will cause the socket to block forever.
      tv.tv_usec = 10000;
   #else
      tv.tv_usec = 100;
   #endif

   #ifdef UNIX
      // Set non-blocking I/O
      // UNIX does not support SO_RCVTIMEO
      int opts = fcntl(m_iSocket, F_GETFL);
      if (-1 == fcntl(m_iSocket, F_SETFL, opts | O_NONBLOCK))
         throw CUDTException(1, 3, NET_ERROR);
   #elif WIN32
      DWORD ot = 1; //milliseconds
      if (setsockopt(m_iSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&ot, sizeof(DWORD)) < 0)
         throw CUDTException(1, 3, NET_ERROR);
   #else
      // Set receiving time-out value
      if (setsockopt(m_iSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(timeval)) < 0)
         throw CUDTException(1, 3, NET_ERROR);
   #endif
}
Exemplo n.º 3
0
UDTSOCKET CUDTUnited::newSocket(int af, int type)
{
	if ((type != SOCK_STREAM) && (type != SOCK_DGRAM))
		throw CUDTException(5, 3, 0);

	CUDTSocket* ns = NULL;

	try
	{
		ns = new CUDTSocket;
		ns->m_pUDT = new CUDT;
		if (AF_INET == af)
		{
			ns->m_pSelfAddr = (sockaddr*)(new sockaddr_in);
			((sockaddr_in*)(ns->m_pSelfAddr))->sin_port = 0;
		}
		else
		{
			ns->m_pSelfAddr = (sockaddr*)(new sockaddr_in6);
			((sockaddr_in6*)(ns->m_pSelfAddr))->sin6_port = 0;
		}
	}
	catch (...)
	{
		delete ns;
		throw CUDTException(3, 2, 0);
	}

	CGuard::enterCS(m_IDLock);
	ns->m_SocketID = -- m_SocketID;
	CGuard::leaveCS(m_IDLock);

	ns->m_Status = INIT;
	ns->m_ListenSocket = 0;
	ns->m_pUDT->m_SocketID = ns->m_SocketID;
	ns->m_pUDT->m_iSockType = (SOCK_STREAM == type) ? UDT_STREAM : UDT_DGRAM;
	ns->m_pUDT->m_iIPversion = ns->m_iIPversion = af;
	ns->m_pUDT->m_pCache = m_pCache;

	// protect the m_Sockets structure.
	CGuard::enterCS(m_ControlLock);
	try
	{
		m_Sockets[ns->m_SocketID] = ns;
	}
	catch (...)
	{
		//failure and rollback
		CGuard::leaveCS(m_ControlLock);
		delete ns;
		ns = NULL;
	}
	CGuard::leaveCS(m_ControlLock);

	if (NULL == ns)
		throw CUDTException(3, 2, 0);

	return ns->m_SocketID;
}
Exemplo n.º 4
0
int CUDTUnited::postRecv(UDTSOCKET u, const sockaddr* addr, const char* buf, uint32_t len)
{
	CUDTSocket* s = locate(u);
	if (NULL == s)
		throw CUDTException(5, 4, 0);

	s->m_pUDT->m_pRcvQueue->postRecv(addr, buf, len);
	return 0;
}
Exemplo n.º 5
0
int CUDTUnited::listen(const UDTSOCKET u, const sockaddr* peer, int backlog)
{
	CUDTSocket* s = locate(u);
	if (NULL == s)
		throw CUDTException(5, 4, 0);

	CGuard cg(s->m_ControlLock);

	// do nothing if the socket is already listening
	if (LISTENING == s->m_Status)
		return 0;

	// a socket can listen only if is in OPENED status
	if (OPENED != s->m_Status)
		throw CUDTException(5, 5, 0);

	// listen is not supported in rendezvous connection setup
	if (s->m_pUDT->m_bRendezvous)
		throw CUDTException(5, 7, 0);

	if (backlog <= 0)
		throw CUDTException(5, 3, 0);

	s->m_uiBackLog = backlog;

	try
	{
		s->m_pQueuedSockets = new std::set<UDTSOCKET>;
		s->m_pAcceptSockets = new std::set<UDTSOCKET>;
	}
	catch (...)
	{
		delete s->m_pQueuedSockets;
		delete s->m_pAcceptSockets;
		throw CUDTException(3, 2, 0);
	}

	s->m_pUDT->listen(peer);

	s->m_Status = LISTENING;

	return 0;
}
Exemplo n.º 6
0
void CChannel::open(const sockaddr* addr)
{
    // construct an socket
    m_iSocket = socket(m_iIPversion, SOCK_DGRAM, 0);

#ifdef WIN32
    if (INVALID_SOCKET == m_iSocket)
#else
    if (m_iSocket < 0)
#endif
        throw CUDTException(1, 0, NET_ERROR);

    if (NULL != addr)
    {
        socklen_t namelen = m_iSockAddrSize;

        if (0 != bind(m_iSocket, addr, namelen))
            throw CUDTException(1, 3, NET_ERROR);
    }
    else
    {
        //sendto or WSASendTo will also automatically bind the socket
        addrinfo hints;
        addrinfo* res;

        memset(&hints, 0, sizeof(struct addrinfo));

        hints.ai_flags = AI_PASSIVE;
        hints.ai_family = m_iIPversion;
        hints.ai_socktype = SOCK_DGRAM;

        if (0 != getaddrinfo(NULL, "0", &hints, &res))
            throw CUDTException(1, 3, NET_ERROR);

        if (0 != bind(m_iSocket, res->ai_addr, res->ai_addrlen))
            throw CUDTException(1, 3, NET_ERROR);

        freeaddrinfo(res);
    }

    setUDPSockOpt();
}
Exemplo n.º 7
0
void CChannel::setUDPSockOpt()
{
#if defined(BSD) || defined(OSX)
    // BSD system will fail setsockopt if the requested buffer size exceeds system maximum value
    int maxsize = 64000;
    if (0 != setsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char*)&m_iRcvBufSize, sizeof(int)))
        setsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char*)&maxsize, sizeof(int));
    if (0 != setsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char*)&m_iSndBufSize, sizeof(int)))
        setsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char*)&maxsize, sizeof(int));
#else
    // for other systems, if requested is greated than maximum, the maximum value will be automactally used
    if ((0 != setsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char*)&m_iRcvBufSize, sizeof(int))) ||
            (0 != setsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char*)&m_iSndBufSize, sizeof(int))))
        throw CUDTException(1, 3, NET_ERROR);
#endif

    timeval tv;
    tv.tv_sec = 0;
#if defined (BSD) || defined (OSX)
    // Known BSD bug as the day I wrote this code.
    // A small time out value will cause the socket to block forever.
    tv.tv_usec = 10000;
#else
    tv.tv_usec = 100;
#endif

#ifdef UNIX
    // Set non-blocking I/O
    // UNIX does not support SO_RCVTIMEO
    int opts = fcntl(m_iSocket, F_GETFL);
    if (-1 == fcntl(m_iSocket, F_SETFL, opts | O_NONBLOCK))
        throw CUDTException(1, 3, NET_ERROR);
#elif WIN32
    DWORD ot = 1; //milliseconds
    if (0 != setsockopt(m_iSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&ot, sizeof(DWORD)))
        throw CUDTException(1, 3, NET_ERROR);
#else
    // Set receiving time-out value
    if (0 != setsockopt(m_iSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(timeval)))
        throw CUDTException(1, 3, NET_ERROR);
#endif
}
Exemplo n.º 8
0
CUDT* CUDTUnited::lookup(const UDTSOCKET u)
{
	// protects the m_Sockets structure
	CGuard cg(m_ControlLock);

	std::map<UDTSOCKET, CUDTSocket*>::iterator i = m_Sockets.find(u);

	if ((i == m_Sockets.end()) || (i->second->m_Status == CLOSED))
		throw CUDTException(5, 4, 0);

	return i->second->m_pUDT;
}
Exemplo n.º 9
0
int CUDTUnited::connect(const UDTSOCKET u, const UDPSOCKET* udpsaock, const sockaddr* name, int namelen)
{
	CUDTSocket* s = locate(u);
	if (NULL == s)
		throw CUDTException(5, 4, 0);

	CGuard cg(s->m_ControlLock);

	// check the size of SOCKADDR structure
	if (AF_INET == s->m_iIPversion)
	{
		if (namelen != sizeof(sockaddr_in))
			throw CUDTException(5, 3, 0);
	}
	else
	{
		if (namelen != sizeof(sockaddr_in6))
			throw CUDTException(5, 3, 0);
	}

	// a socket can "connect" only if it is in INIT or OPENED status
	if (INIT == s->m_Status)
	{
		if (!s->m_pUDT->m_bRendezvous)
		{
			s->m_pUDT->open();
			updateMux(s, name, udpsaock);
			s->m_Status = OPENED;
		}
		else
			throw CUDTException(5, 8, 0);
	}
	else if (OPENED != s->m_Status)
		throw CUDTException(5, 2, 0);

	// connect_complete() may be called before connect() returns.
	// So we need to update the status before connect() is called,
	// otherwise the status may be overwritten with wrong value (CONNECTED vs. CONNECTING).
	s->m_Status = CONNECTING;
	try
	{
		s->m_pUDT->connect(name);
	}
	catch (CUDTException e)
	{
		s->m_Status = OPENED;
		throw e;
	}

	// record peer address
	delete s->m_pPeerAddr;
	if (AF_INET == s->m_iIPversion)
	{
		s->m_pPeerAddr = (sockaddr*)(new sockaddr_in);
		memcpy(s->m_pPeerAddr, name, sizeof(sockaddr_in));
	}
	else
	{
		s->m_pPeerAddr = (sockaddr*)(new sockaddr_in6);
		memcpy(s->m_pPeerAddr, name, sizeof(sockaddr_in6));
	}

	return 0;
}