/* * 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 }
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; }
/* * 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; } } }