#include #include #include #include #include "util.h" /* ==================== Static Data ==================== */ #ifdef WINDOWS /* Info written when starting up WinSock */ WSADATA wsadata; #else /* Terminal settings for getch emulation */ struct termios oldterm, newterm; #endif /* ==================== Set-up and Tear-down ==================== */ int util_init() { #ifdef WINDOWS WSAStartup(MAKEWORD(2, 2), &wsadata); #else tcgetattr(STDIN_FILENO, &oldterm); newterm = oldterm; newterm.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &newterm); #endif return 0; } void util_cleanup() { #ifdef WINDOWS WSACleanup(); #else tcsetattr(STDIN_FILENO, TCSANOW, &oldterm); #endif } /* ==================== Thread Interface ==================== */ int thread_create(Thread *thread, ThreadFunc func, ThreadArg arg) { assert(thread); assert(func); #ifdef WINDOWS *thread = CreateThread(NULL, 0, func, arg, 0, NULL); #else pthread_create(thread, NULL, func, arg); #endif return 0; } void thread_destroy(Thread *thread) { #ifdef WINDOWS CloseHandle(*thread); #endif } void thread_join(Thread *thread) { #ifdef WINDOWS WaitForSingleObject(*thread, INFINITE); #else pthread_join(*thread, NULL); #endif } /* ==================== Socket Interface ==================== */ int socket_open(Socket *sock, const char *hostname, const char *port) { struct addrinfo *info, hints; int result; assert(sock); assert(port); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; result = getaddrinfo(hostname, port, &hints, &info); if (result == 0) { *sock = socket(info->ai_family, info->ai_socktype, info->ai_protocol); if (*sock == INVALID_SOCKET) socket_close(sock); else result = connect(*sock, info->ai_addr, info->ai_addrlen); freeaddrinfo(info); } return result; } int socket_server(Socket *sock, const char *port) { struct addrinfo *info, hints; int result; assert(sock); assert(port); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; result = getaddrinfo(NULL, port, &hints, &info); if (result == 0) { *sock = socket(info->ai_family, info->ai_socktype, info->ai_protocol); if (*sock == INVALID_SOCKET) socket_close(sock); else { result = bind(*sock, info->ai_addr, info->ai_addrlen); if (result != 0) socket_close(sock); else result = listen(*sock, 1); } freeaddrinfo(info); } return result; } int socket_accept(Socket *sock, Socket *client) { assert(sock); assert(client); *client = accept(*sock, NULL, NULL); if (*client == INVALID_SOCKET) return -1; return 0; } void socket_close(Socket *sock) { assert(sock); #ifdef WINDOWS /*shutdown(*sock, SD_BOTH);*/ closesocket(*sock); #else /*shutdown(*sock, SHUT_RDWR);*/ close(*sock); #endif } int socket_write(Socket *sock, const char *buffer, size_t count) { assert(sock); assert(buffer); #ifdef WINDOWS return send(*sock, buffer, count, 0); #else return write(*sock, buffer, count); #endif } int socket_read(Socket *sock, char *buffer, size_t count) { assert(sock); assert(buffer); #ifdef WINDOWS return recv(*sock, buffer, count, 0); #else return read(*sock, buffer, count); #endif } /* ==================== Minor Interface ==================== */ void sleep_ms(unsigned int ms) { #ifdef WINDOWS Sleep(ms); #else while (ms >= 1000) { sleep(1); ms -= 1000; } if (ms > 0) usleep(ms * 1000); #endif } void emit_beep(unsigned int val) { #ifdef WINDOWS /* Compute a value somewhere in [37, 32767] based on the 8 LSB of 'val'. However, the following function will not work for XP-64bit or Vista. */ DWORD freq = (25000.0 / 256) * val + 37; Beep(freq, BEEP_DURATION); #else /* In my tests, I could not get ioctl() to work with producing variable tones, and even then, it might require root access. This monotone beep will hopefully be replaced soon for POSIX systems. */ putchar('\a'); #endif }