Exemple #1
0
static void nlPrepareClose(NLsocket socket) {
	if(nlIsValidSocket(socket) != NL_TRUE) return;
	
	struct Unlocker {
		NLsocket socket;
		~Unlocker() {
			nlUnlockSocket(socket, NL_BOTH);
		}
		Unlocker(NLsocket s) : socket(s) {}
	};
	
	if(nlLockSocket(socket, NL_BOTH) == NL_FALSE)
	{
		return;
	}
	
	Unlocker unlocker(socket);
	
	// code copied&modified from sock_Close
	// The advantage we have here is that we don't lock the whole socket array.
	// nlClose is doing this, so if we would hang in nlClose, we block the
	// *whole* HawkNL system (or at least actions like opening new sockets etc.)!
	
	nl_socket_t     *sock = nlSockets[socket];
	struct ip_mreq  mreq;
    
	if(sock->type == NL_UDP_MULTICAST)
	{
		/* leave the multicast group */
		mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)&sock->addressout)->sin_addr.s_addr;
		mreq.imr_interface.s_addr = INADDR_ANY; //bindaddress;
        
		(void)setsockopt((SOCKET)sock->realsocket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
		 (char *)&mreq, (int)sizeof(mreq));
	}
	if(sock->type == NL_RELIABLE_PACKETS)
	{
		/* check for unsent data */
		if(sock->sendlen > 0)
		{
			int tries = 200;

			/* 200 * 50 ms = up to a 10 second delay to allow data to be sent */
			while(tries-- > 0 && sock->sendlen > 0)
			{
				SDL_Delay(50);
			}
		}
		
		// oh just f**k it
		sock->sendlen = 0;
	}
	if((sock->type == NL_RELIABLE_PACKETS || sock->type == NL_RELIABLE) && sock->listen == NL_FALSE)
	{
		struct linger l = {1, 10};

		(void)setsockopt((SOCKET)sock->realsocket, SOL_SOCKET, SO_LINGER, (const char *)&l, (int)sizeof(l));
	}
	(void)closesocket((SOCKET)sock->realsocket);
}
Exemple #2
0
NL_EXP NLboolean NL_APIENTRY nlGroupDeleteSocket(NLint group, NLsocket socket)
{
    NLint       realgroup = group - NL_FIRST_GROUP;
    NLint       i;
    nl_group_t  *pgroup = NULL;

    if(groups == NULL)
    {
        nlSetError(NL_NO_NETWORK);
        return NL_FALSE;
    }
    if(realgroup < 0)
    {
        nlSetError(NL_INVALID_GROUP);
        return NL_FALSE;
    }

    /* delete the socket from the group */
    if(nlMutexLock(&grouplock) == NL_FALSE)
    {
        return NL_FALSE;
    }
    pgroup = groups[realgroup];
    for(i=0;i<pgroup->numsockets;i++)
    {
        /* check for match */
        if(pgroup->sockets[i] == socket)
            break;
    }
    if(i == pgroup->numsockets)
    {
        /* did not find the socket */
        (void)nlMutexUnlock(&grouplock);
        nlSetError(NL_SOCKET_NOT_FOUND);
        return NL_FALSE;
    }
    /* now pgroup[i] points to the socket to delete */
    /* shift all other sockets down to close the gap */
    i++;
    for(;i<pgroup->maxsockets;i++)
    {
        pgroup->sockets[i - 1] = pgroup->sockets[i];
        /* check for end of list */
        if(pgroup->sockets[i] == -1)
            break;
    }
    pgroup->numsockets--;
    if(pgroup->fdset != NULL)
    {
        /* make sure the socket is valid */
        if(nlIsValidSocket(socket) == NL_TRUE)
        {
            SOCKET realsock;

            realsock = (SOCKET)nlSockets[socket]->realsocket;
            FD_CLR(realsock, pgroup->fdset);
        }
        else
        {
            /* the socket was already closed */
            /* free the fdset so that it can be rebuilt */
            free(pgroup->fdset);
            pgroup->fdset = NULL;
            (void)nlMutexUnlock(&grouplock);
            nlSetError(NL_INVALID_SOCKET);
            return NL_FALSE;
        }
    }
    if(nlMutexUnlock(&grouplock) == NL_FALSE)
    {
        return NL_FALSE;
    }
    return NL_TRUE;
}
Exemple #3
0
NL_EXP NLboolean NL_APIENTRY nlGroupAddSocket(NLint group, NLsocket socket)
{
    NLint       realgroup = group - NL_FIRST_GROUP;
    NLint       i;
    nl_group_t  *pgroup = NULL;

    if(groups == NULL)
    {
        nlSetError(NL_NO_NETWORK);
        return NL_FALSE;
    }
    if(realgroup < 0)
    {
        nlSetError(NL_INVALID_GROUP);
        return NL_FALSE;
    }

    /* add the socket to the group */
    if(nlMutexLock(&grouplock) == NL_FALSE)
    {
        return NL_FALSE;
    }
    pgroup = groups[realgroup];
    /* allocate more sockets as needed */
    if(pgroup->numsockets == pgroup->maxsockets)
    {
        NLint       oldmax = pgroup->maxsockets;
        NLint       j;
        NLsocket    *newsockets;

        if(oldmax == NL_MAX_GROUP_SOCKETS)
        {
            (void)nlMutexUnlock(&grouplock);
            nlSetError(NL_OUT_OF_GROUP_SOCKETS);
            return NL_FALSE;
        }
        pgroup->maxsockets *= 2;
        if(pgroup->maxsockets > NL_MAX_GROUP_SOCKETS)
        {
            pgroup->maxsockets = NL_MAX_GROUP_SOCKETS;
        }
        if((newsockets = (NLsocket *)realloc(pgroup->sockets, pgroup->maxsockets * sizeof(NLsocket *))) == NULL)
        {
            pgroup->maxsockets = oldmax;
            (void)nlMutexUnlock(&grouplock);
            nlSetError(NL_OUT_OF_MEMORY);
            return NL_FALSE;
        }
        /* set the new sockets to -1 */
        for(j=oldmax;j<pgroup->maxsockets;j++)
        {
            newsockets[j] = -1;
        }
        pgroup->sockets = newsockets;
    }

    for(i=0;i<pgroup->maxsockets;i++)
    {
        if(pgroup->sockets[i] == -1)
        {
            pgroup->sockets[i] = socket;
            if(pgroup->fdset != NULL)
            {
                SOCKET realsock;

                /* make sure the socket is valid */
                if(nlIsValidSocket(socket) == NL_FALSE)
                {
                    (void)nlMutexUnlock(&grouplock);
                    nlSetError(NL_INVALID_SOCKET);
                    return NL_FALSE;
                }
                realsock = (SOCKET)nlSockets[socket]->realsocket;
                FD_SET(realsock, pgroup->fdset);
                if(pgroup->highest < realsock + 1)
                {
                    pgroup->highest = realsock + 1;
                }
            }
            break;
        }
    }
    if(i == pgroup->maxsockets)
    {
        (void)nlMutexUnlock(&grouplock);
        nlSetError(NL_OUT_OF_GROUP_SOCKETS);
        return NL_FALSE;
    }
    pgroup->numsockets++;
    if(nlMutexUnlock(&grouplock) == NL_FALSE)
    {
        return NL_FALSE;
    }
    return NL_TRUE;
}
NLint loopback_PollGroup(NLint group, NLenum name, NLsocket *sockets, NLint number, NLint timeout)
{
    NLint           count = 0;
    NLint           numsockets = NL_MAX_GROUP_SOCKETS;
    NLsocket        temp[NL_MAX_GROUP_SOCKETS];

    nlGroupGetSockets(group, (NLint *)&temp, &numsockets);
    if(numsockets < 0)
    {
        /* any error is set by nlGroupGetSockets */
        return NL_INVALID;
    }
    if(numsockets == 0)
    {
        return 0;
    }

    switch(name) {

    case NL_READ_STATUS:
        {
            NLint   i = 0;

            while(numsockets-- > 0)
            {
                /* check for a packet */
                nl_socket_t *sock;

                if(nlIsValidSocket(temp[i]) != NL_TRUE)
                {
                    nlSetError(NL_INVALID_SOCKET);
                    return NL_INVALID;
                }
                sock = nlSockets[temp[i]];

                if(sock->inlen[sock->nextinused] > 0)
                {
                    *sockets = temp[i];
                    sockets++;
                    count++;
                    if(count > number)
                    {
                        nlSetError(NL_BUFFER_SIZE);
                        return NL_INVALID;
                    }
                }
                i++;
            }
        }
        break;

    case NL_WRITE_STATUS:
        {
            NLint   i = 0;

            while(numsockets-- > 0)
            {
                nl_socket_t *sock;

                if(nlIsValidSocket(temp[i]) != NL_TRUE)
                {
                    nlSetError(NL_INVALID_SOCKET);
                    return NL_INVALID;
                }
                sock = nlSockets[temp[i]];

                /* check for a free packet if reliable and connected */
                if((sock->type == NL_RELIABLE || sock->type == NL_RELIABLE_PACKETS)
                    && (sock->connecting == NL_TRUE || sock->connected == NL_TRUE))
                {
                    nl_socket_t *othersock = nlSockets[sock->consock];

                    if(othersock->nextinfree == NL_INVALID)
                    {
                        continue;
                    }
                }
                /* add the socket to the list */
                *sockets = temp[i];
                sockets++;
                count++;
                if(count > number)
                {
                    nlSetError(NL_BUFFER_SIZE);
                    return NL_INVALID;
                }
                i++;
            }
        }
        break;

    default:
        nlSetError(NL_INVALID_ENUM);
        return NL_INVALID;
    }
    return count;
}
NLint loopback_Write(NLsocket socket, NLvoid *buffer, NLint nbytes)
{
    nl_socket_t *sock = nlSockets[socket];
    nl_socket_t *othersock;
    NLint       s[NL_MAX_GROUP_SOCKETS];
    NLint       number = NL_MAX_GROUP_SOCKETS;
    NLint       i;
    NLint       count;

    switch (sock->type) {

    case NL_RELIABLE:
    case NL_UNRELIABLE:
    case NL_RELIABLE_PACKETS:
    default:
        {
            if(sock->connected == NL_TRUE)
            {
                /* check for broken connection */
                if(sock->consock == NL_INVALID)
                {
                    nlSetError(NL_CON_TERM);
                    return NL_INVALID;
                }
                count = loopback_WritePacket(sock->consock, buffer, nbytes, sock->localport);
            }
            else if(sock->connecting == NL_TRUE)
            {
                nlSetError(NL_CON_PENDING);
                return NL_INVALID;
            }
            count = nbytes;
            nlGroupGetSockets(loopgroup, s, &number);
            for(i=0;i<number;i++)
            {
                if(nlIsValidSocket(s[i]) == NL_TRUE)
                {
                    othersock = nlSockets[s[i]];

                    if(sock->remoteport == othersock->localport &&
                        othersock->connected == NL_FALSE &&
                        sock->type == othersock->type)
                    {
                        (void)loopback_WritePacket(s[i], buffer, nbytes, sock->localport);
                    }
                }
            }
        }
        break;
    case NL_BROADCAST:
        {
            count = nbytes;
            nlGroupGetSockets(loopgroup, s, &number);
            for(i=0;i<number;i++)
            {
                if(nlIsValidSocket(s[i]) == NL_TRUE)
                {
                    othersock = nlSockets[s[i]];

                    if(sock->localport == othersock->localport &&
                        sock->type == othersock->type)
                    {
                        (void)loopback_WritePacket(s[i], buffer, nbytes, sock->localport);
                    }
                }
            }
        }
    }

    return count;
}
Exemple #6
0
// modified sock_Write of sock.c from HawkNL
// returns true if socket is connected and data could be send
static bool nlUpdateState(NLsocket socket)
{
	if(nlIsValidSocket(socket) != NL_TRUE) return false;
	
	struct Unlocker {
		NLsocket socket;
		~Unlocker() {
			nlUnlockSocket(socket, NL_BOTH);
		}
		Unlocker(NLsocket s) : socket(s) {}
	};
	
	if(nlLockSocket(socket, NL_BOTH) == NL_FALSE)
	{
		return false;
	}
	
	Unlocker unlocker(socket);
	
	nl_socket_t *sock = nlSockets[socket];
	NLint       count = 0;

	if((sock->type == NL_RELIABLE) || (sock->type == NL_RELIABLE_PACKETS)) /* TCP */
	{
		if(sock->connecting == NL_TRUE)
		{
			fd_set          fdset;
			struct timeval  t = {0,0};
			int             serrval = -1;
			socklen_t       serrsize = (socklen_t)sizeof(serrval);


			FD_ZERO(&fdset);
			FD_SET((SOCKET)sock->realsocket, &fdset);
			if(select(sock->realsocket + 1, NULL, &fdset, NULL, &t) == 1)
			{
				/* Check the socket status */
				(void)getsockopt( sock->realsocket, SOL_SOCKET, SO_ERROR, (char *)&serrval, &serrsize );
				if(serrval != 0)
				{
					if(serrval == ECONNREFUSED)
					{
						nlSetError(NL_CON_REFUSED);
					}
					else if(serrval == EINPROGRESS || serrval == EWOULDBLOCK)
					{
						nlSetError(NL_CON_PENDING);
					}
					return false;
				}
				/* the connect has completed */
				sock->connected = NL_TRUE;
				sock->connecting = NL_FALSE;
			}
			else
			{
				/* check for a failed connect */
				FD_ZERO(&fdset);
				FD_SET((SOCKET)sock->realsocket, &fdset);
				if(select(sock->realsocket + 1, NULL, NULL, &fdset, &t) == 1)
				{
					nlSetError(NL_CON_REFUSED);
				}
				else
				{
					nlSetError(NL_CON_PENDING);
				}
				return false;
			}
		}
		/* check for reliable packets */
		if(sock->type == NL_RELIABLE_PACKETS)
		{
			return true;
		}
		return true;
	}
	else /* unconnected UDP */
	{
		/* check for a non-blocking connection pending */
		if(sock->connecting == NL_TRUE)
		{
			nlSetError(NL_CON_PENDING);
			return false;
		}
		/* check for a connection error */
		if(sock->conerror == NL_TRUE)
		{
			nlSetError(NL_CON_REFUSED);
			return false;
		}
		if(sock->type == NL_BROADCAST)
		{
			((struct sockaddr_in *)&sock->addressin)->sin_addr.s_addr = INADDR_BROADCAST;
		}
		if(sock->type == NL_UDP_MULTICAST)
		{
			return true;
		}
		else if(sock->connected == NL_TRUE)
		{
			return true;
		}
		else
		{
			return true;
		}
	}
	if(count == SOCKET_ERROR)
	{
		return false;
	}
	return false;
}