Beispiel #1
0
/*
 *   Sleep for a while.  This should simply pause for the given number of
 *   milliseconds, then return.  On multi-tasking systems, this should use
 *   a system API to unschedule the current process for the desired delay;
 *   on single-tasking systems, this can simply sit in a wait loop until
 *   the desired interval has elapsed.  
 */
void os_sleep_ms(long delay_in_milliseconds)
{
#ifdef _WIN32
	Sleep(delay_in_milliseconds);
#else
	usleep(delay_in_milliseconds * 1000);
#endif

#if 0
	/*
	 *   calculate the time when we'll be done by adding the delay to the
	 *   current time
	 */
	done_time = os_get_sys_clock_ms() + delay_in_milliseconds;

	/* loop until the system clock says we're done */
	while (os_get_sys_clock_ms() < done_time)
		/* do nothing but soak up CPU cycles... */;
#endif
}
Beispiel #2
0
char *TadsServerManager::gen_rand_id(void *obj)
{
    /* set up a hashing buffer */
    sha256_ctx s;
    sha256_begin(&s);

    /* add the current date/time to the hash */
    os_time_t timer = os_time(0);
    struct tm *tblock = os_localtime(&timer);
    sha256_hash((unsigned char *)tblock, sizeof(*tblock), &s);

    /* add the system timer to the hash */
    long systime = os_get_sys_clock_ms();
    sha256_hash((unsigned char *)&systime, sizeof(systime), &s);

    /* add the object address to the hash */
    sha256_hash((unsigned char *)obj, sizeof(obj), &s);

    /* add the current stack location to the hash */
    sha256_hash((unsigned char *)&obj, sizeof(void *), &s);

    /* add some random bytes from the operating system */
    unsigned char rbuf[128];
    os_gen_rand_bytes(rbuf, sizeof(rbuf));
    sha256_hash(rbuf, sizeof(rbuf), &s);

    /* compute the hash */
    unsigned char hval[32];
    sha256_end(hval, &s);

    /* convert it to hex, but just keep the low nybbles, for 32 digits */
    char *ret = lib_alloc_str(32);
    int i;
    for (i = 0 ; i < 32 ; ++i)
        ret[i] = nybble2hex(hval[i]);

    /* null-terminate the string */
    ret[i] = '\0';

    /* return the allocated string */
    return ret;
}
Beispiel #3
0
/*
 *   Read bytes from the other side.  Blocks until there's at least one byte
 *   to read, then reads as many bytes into the buffer as we can without
 *   blocking further.  Aborts if either the listener's "quit" or "shutdown"
 *   event is triggered.
 */
long TadsServerThread::read(char *buf, size_t buflen, long minlen,
                            unsigned long timeout)
{
    /* figure the ending time for the wait */
    unsigned long t = os_get_sys_clock_ms(), t_end = t + timeout;

    /* we haven't read any bytes yet */
    long totlen = 0;

    /* if the caller provided a buffer, we can't read past the buffer */
    if (buf != 0 && minlen > (long)buflen)
        minlen = buflen;
    
    /* keep going until we read some data */
    for (;;)
    {
        int len;
        char ibuf[4096], *dst;
        size_t dstlen;

        /* figure the buffer destination and size to read on this round */
        if (buf == 0)
        {
            /* 
             *   There's no buffer, so read into our internal buffer.  Tead
             *   up to the remaining minimum size, or to our available
             *   internal space, whichever is less.  
             */
            dst = ibuf;
            dstlen = (minlen < sizeof(ibuf) ? minlen : sizeof(ibuf));
        }
        else
        {
            /* 
             *   Read into the caller's buffer, after any data we've read so
             *   far, up to the remaining buffer length. 
             */
            dst = buf + totlen;
            dstlen = buflen - totlen;
        }

        /* read the data */
        set_run_state("Receiving");
        len = socket->recv(dst, dstlen);

        /* if an error occurred, check what happened */
        if (len == OS_SOCKET_ERROR)
        {
            /* presume failure */
            int ok = FALSE;
            
            /* if this is a would-block error, wait for data to arrive */
            if (socket->last_error() == OS_EWOULDBLOCK)
            {
                /* 
                 *   No data available - wait until we receive at least one
                 *   byte, or until the 'quit' event is signaled or a timeout
                 *   occurs.  Figure the next timeout expiration, if we have
                 *   a timeout at all.  
                 */
                if (timeout != OS_FOREVER)
                {
                    /* if we're already past the timeout expiration, fail */
                    t = os_get_sys_clock_ms();
                    if (t > t_end)
                        return -1;

                    /* figure the remaining timeout interval */
                    timeout = t_end - t;
                }

                /* wait */
                set_run_state("Waiting(receive)");
                OS_Waitable *w[] = {
                    socket, listener->quit_evt, listener->shutdown_evt
                };
                if (OS_Waitable::multi_wait(3, w, timeout) == OSWAIT_EVENT + 0)
                {
                    /* the socket is now ready - reset it and keep going */
                    socket->reset_event();
                    ok = TRUE;
                }
            }

            /* if we didn't correct the error, give up */
            if (!ok)
                return -1;
        }
        else if (len == 0)
        {
            /* the socket has been closed - return failure */
            set_run_state("Error(receiving)");
            return -1;
        }
        else if (len >= minlen)
        {
            /* we've satisfied the request - return the bytes */
            set_run_state("Receive completed");
            return totlen + len;
        }
        else
        {
            /* 
             *   We've read some data, but not enough to satisfy the minimum
             *   length request.  Add the current chunk to the total read so
             *   far, and deduct it from the remaining minimum.  
             */
            totlen += len;
            minlen -= len;
        }
    }
}