diff --git a/xorg/tests/client.sh b/xorg/tests/client.sh new file mode 100755 index 00000000..dc264560 --- /dev/null +++ b/xorg/tests/client.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +xhost + + +if ! [ -d .nx ] +then + mkdir .nx +fi + +export LD_LIBRARY_PATH=$PWD + +./nxproxy -S nx/nx,session=session,id=jay,root=.nx,connect=127.0.0.1:10,delta=1,stream=1,data=1 + diff --git a/xorg/tests/server.sh b/xorg/tests/server.sh new file mode 100755 index 00000000..df6e894b --- /dev/null +++ b/xorg/tests/server.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +export LD_LIBRARY_PATH=$PWD + +#./nxagent -R -bs -dpi 96 -geometry 1024x768 -noshpix -display nx/nx,link=adsl,delta=1,stream=1,data=1,a8taint=0,cache=4M:9 :9 + +# with cache +#./nxagent -D -bs -ac -dpi 96 -geometry 1024x768 -noshpix -display nx/nx,link=adsl,delta=1,stream=1,data=1,cache=4M:9 :9 + +# without cache +./nxagent -D -bs -ac -dpi 96 -geometry 1024x768 -noshpix -display nx/nx,link=adsl,delta=1,stream=1,data=1,cache=0M:9 :9 + diff --git a/xorg/tests/tcp_proxy/arch.h b/xorg/tests/tcp_proxy/arch.h new file mode 100644 index 00000000..2f3c51a2 --- /dev/null +++ b/xorg/tests/tcp_proxy/arch.h @@ -0,0 +1,80 @@ +/* + Copyright (c) 2004-2007 Jay Sorg + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + +*/ + +#if !defined(ARCH_H) +#define ARCH_H + +/* check endianess */ +#if defined(__sparc__) || defined(__PPC__) || defined(__ppc__) +#define B_ENDIAN +#elif __BYTE_ORDER == __LITTLE_ENDIAN +#define L_ENDIAN +#elif __BYTE_ORDER == __BIG_ENDIAN +#define B_ENDIAN +#endif +/* check if we need to align data */ +#if defined(__sparc__) || defined(__alpha__) || defined(__hppa__) || \ + defined(__AIX__) || defined(__PPC__) || defined(__mips__) || \ + defined(__ia64__) || defined(__ppc__) +#define NEED_ALIGN +#endif + +/* defines for thread creation factory functions */ +#if defined(_WIN32) +#define THREAD_RV unsigned long +#define THREAD_CC __stdcall +#else +#define THREAD_RV void* +#define THREAD_CC +#endif + +#if defined(__BORLANDC__) || defined(_WIN32) +#define APP_CC __fastcall +#define DEFAULT_CC __cdecl +#else +#define APP_CC +#define DEFAULT_CC +#endif + +#if defined(_WIN32) +#if defined(__BORLANDC__) +#define EXPORT_CC _export __cdecl +#else +#define EXPORT_CC +#endif +#else +#define EXPORT_CC +#endif + +typedef char ti8; +typedef unsigned char tui8; +typedef signed char tsi8; +typedef short ti16; +typedef unsigned short tui16; +typedef signed short tsi16; +typedef int ti32; +typedef unsigned int tui32; +typedef signed int tsi32; +typedef long tbus; + +#endif diff --git a/xorg/tests/tcp_proxy/main.c b/xorg/tests/tcp_proxy/main.c new file mode 100644 index 00000000..7bfc747e --- /dev/null +++ b/xorg/tests/tcp_proxy/main.c @@ -0,0 +1,265 @@ + +#include "os_calls.h" + +int g_loc_io_count = 0; // bytes read from local port +int g_rem_io_count = 0; // bytes read from remote port + +static int g_terminated = 0; +static char g_buf[1024 * 32]; + +/*****************************************************************************/ +static int +main_loop(char* local_port, char* remote_ip, char* remote_port, int hexdump) +{ + int lis_sck; + int acc_sck; + int con_sck; + int sel; + int count; + int sent; + int error; + int i; + int acc_to_con; + int con_to_acc; + + acc_to_con = 0; + con_to_acc = 0; + acc_sck = 0; + + /* create the listening socket and setup options */ + lis_sck = g_tcp_socket(); + g_tcp_set_non_blocking(lis_sck); + error = g_tcp_bind(lis_sck, local_port); + if (error != 0) + { + g_writeln("bind failed"); + } + + /* listen for an incomming connection */ + if (error == 0) + { + error = g_tcp_listen(lis_sck); + if (error == 0) + { + g_writeln("listening for connection"); + } + } + + /* accept an incomming connection */ + if (error == 0) + { + while ((!g_terminated) && (error == 0)) + { + acc_sck = g_tcp_accept(lis_sck); + if ((acc_sck == -1) && g_tcp_last_error_would_block(lis_sck)) + { + g_sleep(100); + } + else if (acc_sck == -1) + { + error = 1; + } + else + { + break; + } + } + if (error == 0) + { + error = g_terminated; + } + + /* stop listening */ + g_tcp_close(lis_sck); + lis_sck = 0; + if (error == 0) + { + g_writeln("got connection"); + } + } + + /* connect outgoing socket */ + con_sck = 0; + if (error == 0) + { + con_sck = g_tcp_socket(); + g_tcp_set_non_blocking(con_sck); + error = g_tcp_connect(con_sck, remote_ip, remote_port); + if ((error == -1) && g_tcp_last_error_would_block(con_sck)) + { + error = 0; + i = 0; + while ((!g_tcp_can_send(con_sck, 100)) && (!g_terminated) && (i < 100)) + { + g_sleep(100); + i++; + } + if (i > 99) + { + g_writeln("timout connecting"); + error = 1; + } + if (g_terminated) + { + error = 1; + } + } + if ((error != 0) && (!g_terminated)) + { + g_writeln("error connecting to remote\r\n"); + } + } + while ((!g_terminated) && (error == 0)) + { + sel = g_tcp_select(con_sck, acc_sck); + if (sel == 0) + { + g_sleep(10); + continue; + } + if (sel & 1) + { + // can read from con_sck w/o blocking + count = g_tcp_recv(con_sck, g_buf, 1024 * 16, 0); + error = count < 1; + if (error == 0) + { + g_loc_io_count += count; + con_to_acc += count; + if (hexdump) + { + g_writeln("from remove, the socket from connect"); + g_hexdump(g_buf, count); + } +#if 0 + g_writeln("local_io_count: %d\tremote_io_count: %d", + g_loc_io_count, g_rem_io_count); +#endif + sent = 0; + while ((sent < count) && (error == 0) && (!g_terminated)) + { + i = g_tcp_send(acc_sck, g_buf + sent, count - sent, 0); + if ((i == -1) && g_tcp_last_error_would_block(acc_sck)) + { + g_tcp_can_send(acc_sck, 1000); + } + else if (i < 1) + { + error = 1; + } + else + { + sent += i; + } + } + } + } + if (sel & 2) + { + // can read from acc_sck w/o blocking + count = g_tcp_recv(acc_sck, g_buf, 1024 * 16, 0); + error = count < 1; + if (error == 0) + { + g_rem_io_count += count; + acc_to_con += count; + if (hexdump) + { + g_writeln("from accepted, the socket from accept"); + g_hexdump(g_buf, count); + } +#if 0 + g_writeln("local_io_count: %d\tremote_io_count: %d", + g_loc_io_count, g_rem_io_count); +#endif + sent = 0; + while ((sent < count) && (error == 0) && (!g_terminated)) + { + i = g_tcp_send(con_sck, g_buf + sent, count - sent, 0); + if ((i == -1) && g_tcp_last_error_would_block(con_sck)) + { + g_tcp_can_send(con_sck, 1000); + } + else if (i < 1) + { + error = 1; + } + else + { + sent += i; + } + } + } + } + } + g_tcp_close(lis_sck); + g_tcp_close(con_sck); + g_tcp_close(acc_sck); + g_writeln("acc_to_con %d", acc_to_con); + g_writeln("con_to_acc %d", con_to_acc); + return 0; +} + + +/*****************************************************************************/ +static int +usage(void) +{ + g_writeln("tcp_proxy [dump]"); + return 0; +} + + +/*****************************************************************************/ +void +proxy_shutdown(int sig) +{ + g_writeln("shutting down"); + g_terminated = 1; +} + +void +clear_counters(int sig) +{ + g_writeln("cleared counters at: local_io_count: %d remote_io_count: %d", + g_loc_io_count, g_rem_io_count); + g_loc_io_count = 0; + g_rem_io_count = 0; +} + +/*****************************************************************************/ +int +main(int argc, char** argv) +{ + int dump; + + if (argc < 4) + { + usage(); + return 0; + } + g_init(); + g_signal(2, proxy_shutdown); /* SIGINT */ + g_signal(9, proxy_shutdown); /* SIGKILL */ + g_signal(10, clear_counters);/* SIGUSR1*/ + g_signal(15, proxy_shutdown);/* SIGTERM */ + if (argc < 5) + { + while (!g_terminated) + { + g_loc_io_count = 0; + g_rem_io_count = 0; + main_loop(argv[1], argv[2], argv[3], 0); + } + } + else + { + dump = g_strcasecmp(argv[4], "dump") == 0; + while (!g_terminated) + { + main_loop(argv[1], argv[2], argv[3], dump); + } + } + g_deinit(); + return 0; +} diff --git a/xorg/tests/tcp_proxy/os_calls.c b/xorg/tests/tcp_proxy/os_calls.c new file mode 100644 index 00000000..b17856bc --- /dev/null +++ b/xorg/tests/tcp_proxy/os_calls.c @@ -0,0 +1,1449 @@ +/* + Copyright (c) 2004-2007 Jay Sorg + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + generic operating system calls + + put all the os / arch define in here you want +*/ + +#if defined(_WIN32) +#include +#include +#else +/* fix for solaris 10 with gcc 3.3.2 problem */ +#if defined(sun) || defined(__sun) +#define ctid_t id_t +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include + +#include "os_calls.h" +#include "arch.h" + +/* for clearenv() */ +#if defined(_WIN32) +#else +extern char** environ; +#endif + +/* for solaris */ +#if !defined(PF_LOCAL) +#define PF_LOCAL AF_UNIX +#endif +#if !defined(INADDR_NONE) +#define INADDR_NONE ((unsigned long)-1) +#endif + +/*****************************************************************************/ +void APP_CC +g_init(void) +{ + #if defined(_WIN32) + WSADATA wsadata; + + WSAStartup(2, &wsadata); + #endif +} + + +/*****************************************************************************/ +void APP_CC +g_deinit(void) +{ + #if defined(_WIN32) + WSACleanup(); + #endif +} + + +/*****************************************************************************/ +/* allocate memory, returns a pointer to it, size bytes are allocated, + if zero is non zero, each byte will be set to zero */ +void* APP_CC +g_malloc(int size, int zero) +{ + char* rv; + + rv = (char*)malloc(size); + if (zero) + { + memset(rv, 0, size); + } + return rv; +} + + +/*****************************************************************************/ +/* free the memory pointed to by ptr, ptr can be zero */ +void APP_CC +g_free(void* ptr) +{ + if (ptr != 0) + { + free(ptr); + } +} + + +/*****************************************************************************/ +/* output text to stdout, try to use g_write / g_writeln instead to avoid + linux / windows EOL problems */ +void DEFAULT_CC +g_printf(const char* format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); +} + + +/*****************************************************************************/ +void DEFAULT_CC +g_sprintf(char* dest, const char* format, ...) +{ + va_list ap; + + va_start(ap, format); + vsprintf(dest, format, ap); + va_end(ap); +} + + +/*****************************************************************************/ +void DEFAULT_CC +g_snprintf(char* dest, int len, const char* format, ...) +{ + va_list ap; + + va_start(ap, format); + vsnprintf(dest, len, format, ap); + va_end(ap); +} + + +/*****************************************************************************/ +void DEFAULT_CC +g_writeln(const char* format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); + #if defined(_WIN32) + g_printf("\r\n"); + #else + g_printf("\n"); + #endif +} + + +/*****************************************************************************/ +void DEFAULT_CC +g_write(const char* format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); +} + + +/*****************************************************************************/ +/* produce a hex dump */ +void APP_CC +g_hexdump(char* p, int len) +{ + unsigned char* line; + int i; + int thisline; + int offset; + + line = (unsigned char*)p; + offset = 0; + while (offset < len) + { + g_printf("%04x ", offset); + thisline = len - offset; + if (thisline > 16) + { + thisline = 16; + } + for (i = 0; i < thisline; i++) + { + g_printf("%02x ", line[i]); + } + for (; i < 16; i++) + { + g_printf(" "); + } + for (i = 0; i < thisline; i++) + { + g_printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.'); + } + g_writeln(""); + offset += thisline; + line += thisline; + } +} + + +/*****************************************************************************/ +void APP_CC +g_memset(void* ptr, int val, int size) +{ + memset(ptr, val, size); +} + + +/*****************************************************************************/ +void APP_CC +g_memcpy(void* d_ptr, const void* s_ptr, int size) +{ + memcpy(d_ptr, s_ptr, size); +} + + +/*****************************************************************************/ +int APP_CC +g_getchar(void) +{ + return getchar(); +} + + +/*****************************************************************************/ +int APP_CC +g_tcp_set_no_delay(int sck) +{ + int i; + + i = 1; + #if defined(_WIN32) + setsockopt(sck, IPPROTO_TCP, TCP_NODELAY, (char*)&i, sizeof(i)); + #else + setsockopt(sck, IPPROTO_TCP, TCP_NODELAY, (void*)&i, sizeof(i)); + #endif + return 0; +} + + +/*****************************************************************************/ +int APP_CC +g_tcp_socket(void) +{ + int rv; + int i; + + rv = socket(PF_INET, SOCK_STREAM, 0); + #if defined(_WIN32) + i = 1; + setsockopt(rv, IPPROTO_TCP, TCP_NODELAY, (char*)&i, sizeof(i)); + i = 1; + setsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (char*)&i, sizeof(i)); + i = 8192 * 2; + setsockopt(rv, SOL_SOCKET, SO_SNDBUF, (char*)&i, sizeof(i)); + #else + i = 1; + setsockopt(rv, IPPROTO_TCP, TCP_NODELAY, (void*)&i, sizeof(i)); + i = 1; + setsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (void*)&i, sizeof(i)); + i = 8192 * 2; + setsockopt(rv, SOL_SOCKET, SO_SNDBUF, (void*)&i, sizeof(i)); + #endif + return rv; +} + + +/*****************************************************************************/ +int APP_CC +g_tcp_local_socket(void) +{ + #if defined(_WIN32) + return 0; + #else + return socket(PF_LOCAL, SOCK_STREAM, 0); + #endif +} + + +/*****************************************************************************/ +void APP_CC +g_tcp_close(int sck) +{ + if (sck == 0) + { + return; + } + shutdown(sck, 2); + #if defined(_WIN32) + closesocket(sck); + #else + close(sck); + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_tcp_connect(int sck, const char* address, const char* port) +{ + struct sockaddr_in s; + struct hostent* h; + + g_memset(&s, 0, sizeof(struct sockaddr_in)); + s.sin_family = AF_INET; + s.sin_port = htons(atoi(port)); + s.sin_addr.s_addr = inet_addr(address); + if (s.sin_addr.s_addr == INADDR_NONE) + { + h = gethostbyname(address); + if (h != 0) + { + if (h->h_name != 0) + { + if (h->h_addr_list != 0) + { + if ((*(h->h_addr_list)) != 0) + { + s.sin_addr.s_addr = *((int*)(*(h->h_addr_list))); + } + } + } + } + } + return connect(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in)); +} + + +/*****************************************************************************/ +int APP_CC +g_tcp_set_non_blocking(int sck) +{ + unsigned long i; + + #if defined(_WIN32) + i = 1; + ioctlsocket(sck, FIONBIO, &i); + #else + i = fcntl(sck, F_GETFL); + i = i | O_NONBLOCK; + fcntl(sck, F_SETFL, i); + #endif + return 0; +} + + +/*****************************************************************************/ +int APP_CC +g_tcp_bind(int sck, char* port) +{ + struct sockaddr_in s; + + memset(&s, 0, sizeof(struct sockaddr_in)); + s.sin_family = AF_INET; + s.sin_port = htons(atoi(port)); + s.sin_addr.s_addr = INADDR_ANY; + return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in)); +} + + +/*****************************************************************************/ +int APP_CC +g_tcp_local_bind(int sck, char* port) +{ + #if defined(_WIN32) + return -1; + #else + struct sockaddr_un s; + + memset(&s, 0, sizeof(struct sockaddr_un)); + s.sun_family = AF_UNIX; + strcpy(s.sun_path, port); + return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_un)); + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_tcp_listen(int sck) +{ + return listen(sck, 2); +} + + +/*****************************************************************************/ +int APP_CC +g_tcp_accept(int sck) +{ + struct sockaddr_in s; + #if defined(_WIN32) + signed int i; + #else + unsigned int i; + #endif + + i = sizeof(struct sockaddr_in); + memset(&s, 0, i); + return accept(sck, (struct sockaddr*)&s, &i); +} + + +/*****************************************************************************/ +void APP_CC +g_sleep(int msecs) +{ + #if defined(_WIN32) + Sleep(msecs); + #else + usleep(msecs * 1000); + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_tcp_last_error_would_block(int sck) +{ + #if defined(_WIN32) + return WSAGetLastError() == WSAEWOULDBLOCK; + #else + return (errno == EWOULDBLOCK) || (errno == EINPROGRESS); + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_tcp_recv(int sck, void* ptr, int len, int flags) +{ + #if defined(_WIN32) + return recv(sck, (char*)ptr, len, flags); + #else + return recv(sck, ptr, len, flags); + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_tcp_send(int sck, const void* ptr, int len, int flags) +{ + #if defined(_WIN32) + return send(sck, (const char*)ptr, len, flags); + #else + return send(sck, ptr, len, flags); + #endif +} + + +/*****************************************************************************/ +/* wait 'millis' milliseconds for the socket to be able to write */ +/* returns boolean */ +int APP_CC +g_tcp_can_send(int sck, int millis) +{ + fd_set wfds; + struct timeval time; + int rv; + + time.tv_sec = millis / 1000; + time.tv_usec = (millis * 1000) % 1000000; + FD_ZERO(&wfds); + if (sck > 0) + { + FD_SET(((unsigned int)sck), &wfds); + rv = select(sck + 1, 0, &wfds, 0, &time); + if (rv > 0) + { + return 1; + } + } + return 0; +} + + +/*****************************************************************************/ +/* wait 'millis' milliseconds for the socket to be able to receive */ +/* returns boolean */ +int APP_CC +g_tcp_can_recv(int sck, int millis) +{ + fd_set rfds; + struct timeval time; + int rv; + + time.tv_sec = millis / 1000; + time.tv_usec = (millis * 1000) % 1000000; + FD_ZERO(&rfds); + if (sck > 0) + { + FD_SET(((unsigned int)sck), &rfds); + rv = select(sck + 1, &rfds, 0, 0, &time); + if (rv > 0) + { + return 1; + } + } + return 0; +} + + +/*****************************************************************************/ +int APP_CC +g_tcp_select(int sck1, int sck2) +{ + fd_set rfds; + struct timeval time; + int max; + int rv; + + time.tv_sec = 0; + time.tv_usec = 0; + FD_ZERO(&rfds); + if (sck1 > 0) + { + FD_SET(((unsigned int)sck1), &rfds); + } + if (sck2 > 0) + { + FD_SET(((unsigned int)sck2), &rfds); + } + max = sck1; + if (sck2 > max) + { + max = sck2; + } + rv = select(max + 1, &rfds, 0, 0, &time); + if (rv > 0) + { + rv = 0; + if (FD_ISSET(((unsigned int)sck1), &rfds)) + { + rv = rv | 1; + } + if (FD_ISSET(((unsigned int)sck2), &rfds)) + { + rv = rv | 2; + } + } + else + { + rv = 0; + } + return rv; +} + + +/*****************************************************************************/ +void APP_CC +g_random(char* data, int len) +{ + #if defined(_WIN32) + memset(data, 0x44, len); + #else + int fd; + + memset(data, 0x44, len); + fd = open("/dev/urandom", O_RDONLY); + if (fd == -1) + { + fd = open("/dev/random", O_RDONLY); + } + if (fd != -1) + { + read(fd, data, len); + close(fd); + } + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_abs(int i) +{ + return abs(i); +} + + +/*****************************************************************************/ +int APP_CC +g_memcmp(const void* s1, const void* s2, int len) +{ + return memcmp(s1, s2, len); +} + + +/*****************************************************************************/ +/* returns -1 on error, else return handle or file descriptor */ +int APP_CC +g_file_open(const char* file_name) +{ + #if defined(_WIN32) + return (int)CreateFile(file_name, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + #else + int rv; + + rv = open(file_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (rv == -1) + { + /* can't open read / write, try to open read only */ + rv = open(file_name, O_RDONLY); + } + return rv; + #endif +} + + +/*****************************************************************************/ +/* returns error, always 0 */ +int APP_CC +g_file_close(int fd) +{ + #if defined(_WIN32) + CloseHandle((HANDLE)fd); + #else + close(fd); + #endif + return 0; +} + + +/*****************************************************************************/ +/* read from file, returns the number of bytes read or -1 on error */ +int APP_CC +g_file_read(int fd, char* ptr, int len) +{ + #if defined(_WIN32) + if (ReadFile((HANDLE)fd, (LPVOID)ptr, (DWORD)len, (LPDWORD)&len, 0)) + { + return len; + } + else + { + return -1; + } + #else + return read(fd, ptr, len); + #endif +} + + +/*****************************************************************************/ +/* write to file, returns the number of bytes writen or -1 on error */ +int APP_CC +g_file_write(int fd, char* ptr, int len) +{ + #if defined(_WIN32) + if (WriteFile((HANDLE)fd, (LPVOID)ptr, (DWORD)len, (LPDWORD)&len, 0)) + { + return len; + } + else + { + return -1; + } + #else + return write(fd, ptr, len); + #endif +} + + +/*****************************************************************************/ +/* move file pointer, returns offset on success, -1 on failure */ +int APP_CC +g_file_seek(int fd, int offset) +{ + #if defined(_WIN32) + int rv; + + rv = (int)SetFilePointer((HANDLE)fd, offset, 0, FILE_BEGIN); + if (rv == (int)INVALID_SET_FILE_POINTER) + { + return -1; + } + else + { + return rv; + } + #else + return (int)lseek(fd, offset, SEEK_SET); + #endif +} + + +/*****************************************************************************/ +/* do a write lock on a file */ +/* return boolean */ +int APP_CC +g_file_lock(int fd, int start, int len) +{ + #if defined(_WIN32) + return LockFile((HANDLE)fd, start, 0, len, 0); + #else + struct flock lock; + + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = start; + lock.l_len = len; + if (fcntl(fd, F_SETLK, &lock) == -1) + { + return 0; + } + return 1; + #endif +} + + +/*****************************************************************************/ +/* returns error, always zero */ +int APP_CC +g_set_file_rights(const char* filename, int read, int write) +{ + #if defined(_WIN32) + return 0; + #else + int flags; + + flags = read ? S_IRUSR : 0; + flags |= write ? S_IWUSR : 0; + chmod(filename, flags); + return 0; + #endif +} + + +/*****************************************************************************/ +/* returns error */ +int APP_CC +g_chmod_hex(const char* filename, int flags) +{ + #if defined(_WIN32) + return 0; + #else + int fl; + + fl = 0; + fl |= (flags & 0x4000) ? S_ISUID : 0; + fl |= (flags & 0x2000) ? S_ISGID : 0; + fl |= (flags & 0x1000) ? S_ISVTX : 0; + fl |= (flags & 0x0400) ? S_IRUSR : 0; + fl |= (flags & 0x0200) ? S_IWUSR : 0; + fl |= (flags & 0x0100) ? S_IXUSR : 0; + fl |= (flags & 0x0040) ? S_IRGRP : 0; + fl |= (flags & 0x0020) ? S_IWGRP : 0; + fl |= (flags & 0x0010) ? S_IXGRP : 0; + fl |= (flags & 0x0004) ? S_IROTH : 0; + fl |= (flags & 0x0002) ? S_IWOTH : 0; + fl |= (flags & 0x0001) ? S_IXOTH : 0; + return chmod(filename, fl); + #endif +} + + +/*****************************************************************************/ +/* returns error, always zero */ +int APP_CC +g_mkdir(const char* dirname) +{ + #if defined(_WIN32) + return 0; + #else + mkdir(dirname, S_IRWXU); + return 0; + #endif +} + + +/*****************************************************************************/ +/* gets the current working directory and puts up to maxlen chars in + dirname + always returns 0 */ +char* APP_CC +g_get_current_dir(char* dirname, int maxlen) +{ + #if defined(_WIN32) + GetCurrentDirectory(maxlen, dirname); + return 0; + #else + getcwd(dirname, maxlen); + return 0; + #endif +} + + +/*****************************************************************************/ +/* returns error, zero on success and -1 on failure */ +int APP_CC +g_set_current_dir(char* dirname) +{ + #if defined(_WIN32) + if (SetCurrentDirectory(dirname)) + { + return 0; + } + else + { + return -1; + } + #else + return chdir(dirname); + #endif +} + + +/*****************************************************************************/ +/* returns boolean, non zero if the file exists */ +int APP_CC +g_file_exist(const char* filename) +{ + #if defined(_WIN32) + return 0; // use FileAge(filename) <> -1 + #else + return access(filename, F_OK) == 0; + #endif +} + + +/*****************************************************************************/ +/* returns boolean, non zero if the directory exists */ +int APP_CC +g_directory_exist(const char* dirname) +{ + #if defined(_WIN32) + return 0; // use GetFileAttributes and check return value + // is not -1 and FILE_ATTRIBUT_DIRECTORY bit is set + #else + struct stat st; + + if (stat(dirname, &st) == 0) + { + return S_ISDIR(st.st_mode); + } + else + { + return 0; + } + #endif +} + + +/*****************************************************************************/ +/* returns boolean */ +int APP_CC +g_create_dir(const char* dirname) +{ + #if defined(_WIN32) + // test this + return CreateDirectory(dirname, 0); + #else + return mkdir(dirname, (mode_t)-1) == 0; + #endif +} + + +/*****************************************************************************/ +/* returns boolean */ +int APP_CC +g_remove_dir(const char* dirname) +{ + #if defined(_WIN32) + // test this + return RemoveDirectory(dirname); + #else + return rmdir(dirname) == 0; + #endif +} + + +/*****************************************************************************/ +/* returns non zero if the file was deleted */ +int APP_CC +g_file_delete(const char* filename) +{ + #if defined(_WIN32) + return DeleteFile(filename); + #else + return unlink(filename) != -1; + #endif +} + + +/*****************************************************************************/ +/* returns length of text */ +int APP_CC +g_strlen(const char* text) +{ + if (text == 0) + { + return 0; + } + return strlen(text); +} + + +/*****************************************************************************/ +/* returns dest */ +char* APP_CC +g_strcpy(char* dest, const char* src) +{ + if (src == 0 && dest != 0) + { + dest[0] = 0; + return dest; + } + if (dest == 0 || src == 0) + { + return 0; + } + return strcpy(dest, src); +} + + +/*****************************************************************************/ +/* returns dest */ +char* APP_CC +g_strncpy(char* dest, const char* src, int len) +{ + char* rv; + + if (src == 0 && dest != 0) + { + dest[0] = 0; + return dest; + } + if (dest == 0 || src == 0) + { + return 0; + } + rv = strncpy(dest, src, len); + dest[len] = 0; + return rv; +} + + +/*****************************************************************************/ +/* returns dest */ +char* APP_CC +g_strcat(char* dest, const char* src) +{ + if (dest == 0 || src == 0) + { + return dest; + } + return strcat(dest, src); +} + + +/*****************************************************************************/ +/* if in = 0, return 0 else return newly alloced copy of in */ +char* APP_CC +g_strdup(const char* in) +{ + int len; + char* p; + + if (in == 0) + { + return 0; + } + len = g_strlen(in); + p = (char*)g_malloc(len + 1, 0); + g_strcpy(p, in); + return p; +} + + +/*****************************************************************************/ +int APP_CC +g_strcmp(const char* c1, const char* c2) +{ + return strcmp(c1, c2); +} + + +/*****************************************************************************/ +int APP_CC +g_strncmp(const char* c1, const char* c2, int len) +{ + return strncmp(c1, c2, len); +} + + +/*****************************************************************************/ +int APP_CC +g_strcasecmp(const char* c1, const char* c2) +{ + #if defined(_WIN32) + return stricmp(c1, c2); + #else + return strcasecmp(c1, c2); + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_strncasecmp(const char* c1, const char* c2, int len) +{ + #if defined(_WIN32) + return strnicmp(c1, c2, len); + #else + return strncasecmp(c1, c2, len); + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_atoi(char* str) +{ + return atoi(str); +} + + +/*****************************************************************************/ +int APP_CC +g_pos(char* str, const char* to_find) +{ + char* pp; + + pp = strstr(str, to_find); + if (pp == 0) + { + return -1; + } + return (pp - str); +} + + +/*****************************************************************************/ +long APP_CC +g_load_library(char* in) +{ + #if defined(_WIN32) + return (long)LoadLibrary(in); + #else + return (long)dlopen(in, RTLD_LOCAL | RTLD_LAZY); + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_free_library(long lib) +{ + if (lib == 0) + { + return 0; + } + #if defined(_WIN32) + return FreeLibrary((HMODULE)lib); + #else + return dlclose((void*)lib); + #endif +} + + +/*****************************************************************************/ +/* returns NULL if not found */ +void* APP_CC +g_get_proc_address(long lib, const char* name) +{ + if (lib == 0) + { + return 0; + } + #if defined(_WIN32) + return GetProcAddress((HMODULE)lib, name); + #else + return dlsym((void*)lib, name); + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_system(char* aexec) +{ + #if defined(_WIN32) + return 0; + #else + return system(aexec); + #endif +} + + +/*****************************************************************************/ +char* APP_CC +g_get_strerror(void) +{ + #if defined(_WIN32) + return 0; + #else + return strerror(errno); + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_execvp(const char* p1, char* args[]) +{ + #if defined(_WIN32) + return 0; + #else + return execvp(p1, args); + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_execlp3(const char* a1, const char* a2, const char* a3) +{ + #if defined(_WIN32) + return 0; + #else + return execlp(a1, a2, a3, (void*)0); + #endif +} + + +/*****************************************************************************/ +void APP_CC +g_signal(int sig_num, void (*func)(int)) +{ + #if defined(_WIN32) + #else + signal(sig_num, func); + #endif +} + + +/*****************************************************************************/ +void APP_CC +g_signal_child_stop(void (*func)(int)) +{ + #if defined(_WIN32) + #else + signal(SIGCHLD, func); + #endif +} + + +/*****************************************************************************/ +void APP_CC +g_unset_signals(void) +{ + #if defined(_WIN32) + #else + sigset_t mask; + + sigemptyset(&mask); + sigprocmask(SIG_SETMASK, &mask, NULL); + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_fork(void) +{ + #if defined(_WIN32) + return 0; + #else + return fork(); + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_setgid(int pid) +{ + #if defined(_WIN32) + return 0; + #else + return setgid(pid); + #endif +} + + +/*****************************************************************************/ +/* returns error, zero is success, non zero is error */ +int APP_CC +g_initgroups(const char* user, int gid) +{ + #if defined(_WIN32) + return 0; + #else + return initgroups(user ,gid); + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_setuid(int pid) +{ + #if defined(_WIN32) + return 0; + #else + return setuid(pid); + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_waitchild(void) +{ + #if defined(_WIN32) + return 0; + #else + int wstat; + + return waitpid(0, &wstat, WNOHANG); + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_waitpid(int pid) +{ + #if defined(_WIN32) + return 0; + #else + return waitpid(pid, 0, 0); + #endif +} + + +/*****************************************************************************/ +void APP_CC +g_clearenv(void) +{ + #if defined(_WIN32) + #else + environ = 0; + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_setenv(const char* name, const char* value, int rewrite) +{ + #if defined(_WIN32) + return 0; + #else + return setenv(name, value, rewrite); + #endif +} + + +/*****************************************************************************/ +char* APP_CC +g_getenv(const char* name) +{ + #if defined(_WIN32) + return 0; + #else + return getenv(name); + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_exit(int exit_code) +{ + _exit(exit_code); + return 0; +} + + +/*****************************************************************************/ +int APP_CC +g_getpid(void) +{ + #if defined(_WIN32) + return 0; + #else + return getpid(); + #endif +} + + +/*****************************************************************************/ +int APP_CC +g_sigterm(int pid) +{ + #if defined(_WIN32) + return 0; + #else + return kill(pid, SIGTERM); + #endif +} + + +/*****************************************************************************/ +/* returns 0 if ok */ +int APP_CC +g_getuser_info(const char* username, int* gid, int* uid, char* shell, +char* dir, char* gecos) +{ + #if defined(_WIN32) + return 1; + #else + struct passwd* pwd_1; + + pwd_1 = getpwnam(username); + if (pwd_1 != 0) + { + if (gid != 0) + { + *gid = pwd_1->pw_gid; + } + if (uid != 0) + { + *uid = pwd_1->pw_uid; + } + if (dir != 0) + { + g_strcpy(dir, pwd_1->pw_dir); + } + if (shell != 0) + { + g_strcpy(shell, pwd_1->pw_shell); + } + if (gecos != 0) + { + g_strcpy(gecos, pwd_1->pw_gecos); + } + return 0; + } + return 1; + #endif +} + + +/*****************************************************************************/ +/* returns 0 if ok */ +int APP_CC +g_getgroup_info(const char* groupname, int* gid) +{ + #if defined(_WIN32) + return 1; + #else + struct group* g; + + g = getgrnam(groupname); + if (g != 0) + { + if (gid != 0) + { + *gid = g->gr_gid; + } + return 0; + } + return 1; + #endif +} + + +/*****************************************************************************/ +/* returns error */ +/* if zero is returned, then ok is set */ +int APP_CC +g_check_user_in_group(const char* username, int gid, int* ok) +{ + #if defined(_WIN32) + return 1; + #else + struct group* groups; + int i; + + groups = getgrgid(gid); + if (groups == 0) + { + return 1; + } + *ok = 0; + i = 0; + while (0 != groups->gr_mem[i]) + { + if (0 == g_strcmp(groups->gr_mem[i], username)) + { + *ok = 1; + break; + } + i++; + } + return 0; + #endif +} + + +/*****************************************************************************/ +/* returns the time since the Epoch (00:00:00 UTC, January 1, 1970), + measured in seconds. */ +int APP_CC +g_time1(void) +{ + #if defined(_WIN32) + return GetTickCount() / 1000; + #else + return time(0); + #endif +} diff --git a/xorg/tests/tcp_proxy/os_calls.h b/xorg/tests/tcp_proxy/os_calls.h new file mode 100644 index 00000000..768cc38c --- /dev/null +++ b/xorg/tests/tcp_proxy/os_calls.h @@ -0,0 +1,208 @@ +/* + Copyright (c) 2004-2007 Jay Sorg + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + generic operating system calls +*/ + +#if !defined(OS_CALLS_H) +#define OS_CALLS_H + +#include "arch.h" + +void APP_CC +g_init(void); +void APP_CC +g_deinit(void); +void* APP_CC +g_malloc(int size, int zero); +void APP_CC +g_free(void* ptr); +void DEFAULT_CC +g_printf(const char *format, ...); +void DEFAULT_CC +g_sprintf(char* dest, const char* format, ...); +void DEFAULT_CC +g_snprintf(char* dest, int len, const char* format, ...); +void DEFAULT_CC +g_writeln(const char* format, ...); +void DEFAULT_CC +g_write(const char* format, ...); +void APP_CC +g_hexdump(char* p, int len); +void APP_CC +g_memset(void* ptr, int val, int size); +void APP_CC +g_memcpy(void* d_ptr, const void* s_ptr, int size); +int APP_CC +g_getchar(void); +int APP_CC +g_tcp_set_no_delay(int sck); +int APP_CC +g_tcp_socket(void); +int APP_CC +g_tcp_local_socket(void); +void APP_CC +g_tcp_close(int sck); +int APP_CC +g_tcp_connect(int sck, const char* address, const char* port); +int APP_CC +g_tcp_force_send(int sck, char* data, int len); +int APP_CC +g_tcp_force_recv(int sck, char* data, int len); +int APP_CC +g_tcp_set_non_blocking(int sck); +int APP_CC +g_tcp_bind(int sck, char* port); +int APP_CC +g_tcp_local_bind(int sck, char* port); +int APP_CC +g_tcp_listen(int sck); +int APP_CC +g_tcp_accept(int sck); +int APP_CC +g_tcp_recv(int sck, void* ptr, int len, int flags); +int APP_CC +g_tcp_send(int sck, const void* ptr, int len, int flags); +int APP_CC +g_tcp_last_error_would_block(int sck); +int APP_CC +g_tcp_can_send(int sck, int millis); +int APP_CC +g_tcp_can_recv(int sck, int millis); +int APP_CC +g_tcp_select(int sck1, int sck2); +void APP_CC +g_sleep(int msecs); +void APP_CC +g_random(char* data, int len); +int APP_CC +g_abs(int i); +int APP_CC +g_memcmp(const void* s1, const void* s2, int len); +int APP_CC +g_file_open(const char* file_name); +int APP_CC +g_file_close(int fd); +int APP_CC +g_file_read(int fd, char* ptr, int len); +int APP_CC +g_file_write(int fd, char* ptr, int len); +int APP_CC +g_file_seek(int fd, int offset); +int APP_CC +g_file_lock(int fd, int start, int len); +int APP_CC +g_set_file_rights(const char* filename, int read, int write); +int APP_CC +g_chmod_hex(const char* filename, int flags); +int APP_CC +g_mkdir(const char* dirname); +char* APP_CC +g_get_current_dir(char* dirname, int maxlen); +int APP_CC +g_set_current_dir(char* dirname); +int APP_CC +g_file_exist(const char* filename); +int APP_CC +g_directory_exist(const char* dirname); +int APP_CC +g_create_dir(const char* dirname); +int APP_CC +g_remove_dir(const char* dirname); +int APP_CC +g_file_delete(const char* filename); +int APP_CC +g_strlen(const char* text); +char* APP_CC +g_strcpy(char* dest, const char* src); +char* APP_CC +g_strncpy(char* dest, const char* src, int len); +char* APP_CC +g_strcat(char* dest, const char* src); +char* APP_CC +g_strdup(const char* in); +int APP_CC +g_strcmp(const char* c1, const char* c2); +int APP_CC +g_strncmp(const char* c1, const char* c2, int len); +int APP_CC +g_strcasecmp(const char* c1, const char* c2); +int APP_CC +g_strncasecmp(const char* c1, const char* c2, int len); +int APP_CC +g_atoi(char* str); +int APP_CC +g_pos(char* str, const char* to_find); +long APP_CC +g_load_library(char* in); +int APP_CC +g_free_library(long lib); +void* APP_CC +g_get_proc_address(long lib, const char* name); +int APP_CC +g_system(char* aexec); +char* APP_CC +g_get_strerror(void); +int APP_CC +g_execvp(const char* p1, char* args[]); +int APP_CC +g_execlp3(const char* a1, const char* a2, const char* a3); +void APP_CC +g_signal(int sig_num, void (*func)(int)); +void APP_CC +g_signal_child_stop(void (*func)(int)); +void APP_CC +g_unset_signals(void); +int APP_CC +g_fork(void); +int APP_CC +g_setgid(int pid); +int APP_CC +g_initgroups(const char* user, int gid); +int APP_CC +g_setuid(int pid); +int APP_CC +g_waitchild(void); +int APP_CC +g_waitpid(int pid); +void APP_CC +g_clearenv(void); +int APP_CC +g_setenv(const char* name, const char* value, int rewrite); +char* APP_CC +g_getenv(const char* name); +int APP_CC +g_exit(int exit_code); +int APP_CC +g_getpid(void); +int APP_CC +g_sigterm(int pid); +int APP_CC +g_getuser_info(const char* username, int* gid, int* uid, char* shell, + char* dir, char* gecos); +int APP_CC +g_getgroup_info(const char* groupname, int* gid); +int APP_CC +g_check_user_in_group(const char* username, int gid, int* ok); +int APP_CC +g_time1(void); + +#endif diff --git a/xorg/tests/xdemo/README.txt b/xorg/tests/xdemo/README.txt new file mode 100644 index 00000000..52bda08c --- /dev/null +++ b/xorg/tests/xdemo/README.txt @@ -0,0 +1,3 @@ + +this is a project to develope a program to test xwindows + diff --git a/xorg/tests/xdemo/bmp_parser.c b/xorg/tests/xdemo/bmp_parser.c new file mode 100644 index 00000000..9d3e43c8 --- /dev/null +++ b/xorg/tests/xdemo/bmp_parser.c @@ -0,0 +1,204 @@ +#include +#include +#include +#include +#include +#include +#include "common.h" + +// multi byte values are stored in little endian + +struct bmp_magic +{ + char magic[2]; +}; + +struct bmp_hdr +{ + uint32_t size; // file size in bytes + uint16_t reserved1; + uint16_t reserved2; + uint32_t offset; // offset to image data, in bytes +}; + +struct dib_hdr +{ + uint32_t hdr_size; + int32_t width; + int32_t height; + uint16_t nplanes; + uint16_t bpp; + uint32_t compress_type; + uint32_t image_size; + int32_t hres; + int32_t vres; + uint32_t ncolors; + uint32_t nimpcolors; +}; + +// forward declarations +int parse_bmp(char *filename, struct pic_info *pic_info); +int parse_bmp_24(struct bmp_hdr *bmp_hdr, struct dib_hdr *dib_hdr, int fd, struct pic_info *pic_info); + +int parse_bmp(char *filename, struct pic_info *pic_info) +{ + int got_magic; + int fd; + int rval; + + struct bmp_magic magic; + struct bmp_hdr bmp_hdr; + struct dib_hdr dib_hdr; + + if ((fd = open(filename, O_RDONLY)) < 0) { + printf("error opeing %s\n", filename); + return -1; + } + + // read BMP magic... + if ((rval = read(fd, magic.magic, 2)) != 2) { + fprintf(stderr, "error reading BMP signature from file %s\n", filename); + return -1; + } + + got_magic = 0; + + // ...and confirm that this is indeed a BMP file + if ((magic.magic[0] == 'B') && (magic.magic[1] == 'M')) { + // BM – Windows 3.1x, 95, NT, ... etc + got_magic = 1; + } + else if ((magic.magic[0] == 'B') && (magic.magic[1] == 'A')) { + // BA – OS/2 struct Bitmap Array + got_magic = 1; + } + else if ((magic.magic[0] == 'C') && (magic.magic[1] == 'I')) { + // CI – OS/2 struct Color Icon + got_magic = 1; + } + else if ((magic.magic[0] == 'C') && (magic.magic[1] == 'P')) { + // CP – OS/2 const Color Pointer + got_magic = 1; + } + else if ((magic.magic[0] == 'I') && (magic.magic[1] == 'C')) { + // IC – OS/2 struct Icon + got_magic = 1; + } + else if ((magic.magic[0] == 'P') && (magic.magic[1] == 'T')) { + // PT – OS/2 Pointer + got_magic = 1; + } + + if (!got_magic) { + fprintf(stderr, "%s is not a valid BMP file\n", filename); + return -1; + } + + // read BMP header + if ((rval = read(fd, &bmp_hdr, sizeof(bmp_hdr))) < sizeof(bmp_hdr)) { + fprintf(stderr, "error BMP header from file %s\n", filename); + return -1; + } + + // read DIB header + if ((rval = read(fd, &dib_hdr, sizeof(dib_hdr))) < sizeof(dib_hdr)) { + fprintf(stderr, "error reading DIB header from file %s\n", filename); + return -1; + } + +#if 0 + printf("header size: %d\n", dib_hdr.hdr_size); + printf("width: %d\n", dib_hdr.width); + printf("height: %d\n", dib_hdr.height); + printf("num planes: %d\n", dib_hdr.nplanes); + printf("bpp: %d\n", dib_hdr.bpp); + printf("comp type: %d\n", dib_hdr.compress_type); + printf("image size: %d\n", dib_hdr.image_size); + printf("hres: %d\n", dib_hdr.hres); + printf("vres: %d\n", dib_hdr.vres); + printf("ncolors: %d\n", dib_hdr.ncolors); + printf("nimpcolors: %d\n", dib_hdr.nimpcolors); +#endif + + if (dib_hdr.compress_type) { + printf("TODO: compressed images not yet supported\n"); + return -1; + } + + pic_info->width = dib_hdr.width; + pic_info->height = dib_hdr.height; + + if (dib_hdr.bpp == 24) { + rval = parse_bmp_24(&bmp_hdr, &dib_hdr, fd, pic_info); + } + close(fd); + return rval; +} + +/** + * extract 24bit BMP data from image file + * + * @return 0 on success + * @return -1 on failure + */ + +int parse_bmp_24( + struct bmp_hdr *bmp_hdr, + struct dib_hdr *dib_hdr, + int fd, + struct pic_info *pic_info +) +{ + char *file_data; + char *ptr_file_data; + char *mem_data; + char *ptr_mem_data; + char *cptr; + + int w = dib_hdr->width; // picture width + int h = dib_hdr->height; // picture height + int bpl; // bytes per line + int bytes; + int i; + int j; + + // bytes per image line = width x bytes_per_pixel + padding + i = (w * 3) % 4; + j = (i == 0) ? 0 : 4 - i; + bpl = w * 3 + j; + + // 24 bit depth, no alpha channel + file_data = (char *) malloc(h * bpl); + + // point to first line in image data, which is stored in reverse order + ptr_file_data = (file_data + dib_hdr->image_size) - bpl; + + // 24 bit depth, with alpha channel + mem_data = (char *) malloc(w * h * 4); + ptr_mem_data = mem_data; + + pic_info->pixel_data = ptr_mem_data; + + // seek to beginning of pixel data + lseek(fd, bmp_hdr->offset, SEEK_SET); + + // read all pixel data + bytes = read(fd, file_data, dib_hdr->image_size); + + // convert 24bit to 24 bit with alpha and store in reverse + for (i = 0; i < h; i ++) + { + cptr = ptr_file_data; + for (j = 0; j < w; j++) + { + *ptr_mem_data++ = *cptr++; // blue value + *ptr_mem_data++ = *cptr++; // green value + *ptr_mem_data++ = *cptr++; // red value + *ptr_mem_data++ = 0; // alpha channel + } + ptr_file_data -= bpl; + } + + free(file_data); + return 0; +} diff --git a/xorg/tests/xdemo/common.h b/xorg/tests/xdemo/common.h new file mode 100644 index 00000000..2ce75bba --- /dev/null +++ b/xorg/tests/xdemo/common.h @@ -0,0 +1,19 @@ +#ifndef __XDEMO_H +#define __XDEMO_H + +#define DEBUG + +#ifdef DEBUG +#define dprint(x...) printf(x) +#else +#define dprint(x...) +#endif + +struct pic_info +{ + int width; + int height; + char *pixel_data; +}; + +#endif diff --git a/xorg/tests/xdemo/xdemo.c b/xorg/tests/xdemo/xdemo.c new file mode 100644 index 00000000..073516f0 --- /dev/null +++ b/xorg/tests/xdemo/xdemo.c @@ -0,0 +1,674 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" + +// LK_TODO +// http://tronche.com/gui/x/xlib/GC/convenience-functions/fill-tile-and-stipple.html +// fill stipple + +// drawfonts: XDrawString, XDrawImageString XDrawText XLoadFont XTextExtents +// http://www.ac3.edu.au/SGI_Developer/books/XLib_PG/sgi_html/apa.html +// http://www.ac3.edu.au/SGI_Developer/books/XLib_PG/sgi_html/index.html + +// use jpg lib to convert bmp to jpg and vice versa + +#define MAX_COLORS 5 +#define SCROLL_JUMP 1 // scroll in increments of g_winHeight +#define SCROLL_SMOOTH1 2 // scroll using XPutImage + XCopyArea +#define SCROLL_SMOOTH2 3 // scroll using XPutImage only + +int parse_bmp(char *filename, struct pic_info *); +int drawBMP(char *filename, int scroll_type); +int signal_tcp_proxy(char *proxy_app); + +// globals +Display *g_disp; +Window g_win; +XColor g_colors[MAX_COLORS]; +GC g_gc; +int g_winWidth; +int g_winHeight; +int g_delay_dur; + +void start_timer(struct timeval *tv) +{ + gettimeofday(tv, NULL); +} + + +uint32_t time_elapsed_ms(struct timeval tv) +{ + struct timeval tv_now; + uint32_t dur; + + gettimeofday(&tv_now, NULL); + dur = ((tv_now.tv_sec - tv.tv_sec) * 1000) + ((tv_now.tv_usec - tv.tv_usec) / 1000); + return dur; +} + + +uint32_t time_elapsed_us(struct timeval tv) +{ + struct timeval tv_now; + uint32_t dur; + + gettimeofday(&tv_now, NULL); + dur = ((tv_now.tv_sec - tv.tv_sec) * 1000000) + (tv_now.tv_usec - tv.tv_usec); + return dur; +} + +int drawLines(int count) +{ + int x1; + int y1; + int x2; + int y2; + int i; + int index; + + if (count <= 0) { + return 0; // nothing to do + } + + srandom(time(NULL)); + XClearArea(g_disp, g_win, 0, 0, g_winWidth, g_winHeight, 0); + + for (i = 0, index = 0; i < count; i++) + { + x1 = random() % g_winWidth; + y1 = random() % g_winHeight; + x2 = random() % g_winWidth; + y2 = random() % g_winHeight; + XSetForeground(g_disp, g_gc, g_colors[index++].pixel); + if (index == MAX_COLORS) { + index = 0; + } + // from-to + XDrawLine(g_disp, g_win, g_gc, x1, y1, x2, y2); + XFlush(g_disp); + usleep(g_delay_dur); + } + return 0; +} + +// LK_TODO support user defined w and h + +int drawRectangles(int count) +{ + int x1; + int y1; + int w; + int h; + int i; + int index; + + if (count <= 0) { + return 0; // nothing to do + } + + srandom(time(NULL)); + XClearArea(g_disp, g_win, 0, 0, g_winWidth, g_winHeight, 0); + + for (i = 0, index = 0; i < count; i++) + { + x1 = random() % g_winWidth; + y1 = random() % g_winHeight; + w = 160; + h = 140; + XSetForeground(g_disp, g_gc, g_colors[index++].pixel); + if (index == MAX_COLORS) { + index = 0; + } + //XDrawRectangle(g_disp, g_win, g_gc, x1, y1, w, h); + XFillRectangle(g_disp, g_win, g_gc, x1, y1, w, h); + XFlush(g_disp); + usleep(g_delay_dur); + } + return 0; +} + +int drawFont(int count, char *msg) +{ + int x1; + int y1; + int i; + int index; + +#ifdef CHANGE_FONT_SIZE + int w; + int h; + int actual_count; + char **font_list; +#endif + + if (count <= 0) { + return 0; // nothing to do + } + + srandom(time(NULL)); + XClearArea(g_disp, g_win, 0, 0, g_winWidth, g_winHeight, 0); + +#ifdef CHANGE_FONT_SIZE + font_list = XListFonts(g_disp, "−*−courier−*−*−*−*−0−0−*−*−*−0−*−*", 2000, &actual_count); + if (!font_list) { + printf("actual_count=%d\n", actual_count); + for (i = 0; i < actual_count; i++) + { + printf("%s\n", font_list[i]); + } + XFreeFontNames(font_list); + } + else { + printf("XListFonts() reted NULL\n"); + } +#endif + + srandom(time(NULL)); + + for (i = 0, index = 0; i < count; i++) + { + x1 = random() % g_winWidth; + y1 = random() % g_winHeight; + XSetForeground(g_disp, g_gc, g_colors[index++].pixel); + if (index == MAX_COLORS) { + index = 0; + } + XDrawString(g_disp, g_win, g_gc, x1, y1, msg, strlen(msg)); + XFlush(g_disp); + usleep(g_delay_dur); + } + return 0; // nothing to do +} + +/** + * display a usage message + */ + +void +usage() +{ + printf("usage: xdemo [-l] [-r] [-s] [-f ] [-i ] [-g ] [-c ] [-o ] [-d ] -z\n"); + printf(" -l draw lines\n"); + printf(" -r draw fill rectangles\n"); + printf(" -s draw stipple rectangles\n"); + printf(" -f draw string using fonts\n"); + printf(" -i draw image\n"); + printf(" -g geometry, default is 640x480\n"); + printf(" -c iteration count, default is 5000\n"); + printf(" -d loop delay in micro seconds, default 1000\n"); + printf(" -o define scrolling method\n"); + printf(" -z zero proxy counters for specified application\n\n"); +} + +int main(int argc, char **argv) +{ + XEvent evt; + Colormap colormap; + struct timeval tv; + int screenNumber; + long eventMask; + unsigned long white; + unsigned long black; + Status rc; + int iters; + int opt; + int draw_lines; + int draw_rects; + int draw_stipples; + int draw_fonts; + int draw_image; + int zero_counters; + int scroll_type; + char image_file[256]; + char proxy_app[256]; + char msg[4096]; + + // set some defaults + g_winWidth = 640; + g_winHeight = 480; + iters = 5000; + draw_lines = 1; + draw_rects = 1; + draw_stipples = 1; + draw_fonts = 1; + draw_image = 1; + g_delay_dur = 1000; + scroll_type = SCROLL_SMOOTH1; + zero_counters = 0; + strcpy(image_file, "yosemite.bmp"); + strcpy(msg, "To be or not to be!"); + + // process cmd line args + opterr = 0; + while ((opt = getopt(argc, argv, "lrsg:c:f:i:d:o:z:")) != -1) + { + switch (opt) + { + case 'g': + if (sscanf(optarg, "%dx%d", &g_winWidth, &g_winHeight) != 2) { + fprintf(stderr, "\nerror: invalid geometry specified\n\n"); + usage(); + return -1; + } + break; + + case 'c': + if (sscanf(optarg, "%d", &iters) != 1) { + fprintf(stderr, "\nerror: invalid count specified\n\n"); + usage(); + return -1; + } + break; + + case 'l': + draw_lines = 1; + draw_rects = 0; + draw_stipples = 0; + draw_fonts = 0; + draw_image = 0; + break; + + case 'r': + draw_rects = 1; + draw_lines = 0; + draw_stipples = 0; + draw_fonts = 0; + draw_image = 0; + break; + + case 's': + draw_stipples = 1; + draw_lines = 0; + draw_rects = 0; + draw_fonts = 0; + draw_image = 0; + break; + + case 'f': + if (strlen(optarg) <= 0) { + fprintf(stderr, "\nerror: -f option requires an argument\n\n"); + usage(); + return -1; + } + draw_fonts = 1; + strncpy(msg, optarg, 4096); + draw_lines = 0; + draw_rects = 0; + draw_stipples = 0; + draw_image = 0; + break; + + case 'i': + if (strlen(optarg) <= 0) { + fprintf(stderr, "\nerror: -i option requires an argument\n\n"); + usage(); + return -1; + } + draw_image = 1; + strncpy(image_file, optarg, 255); + draw_lines = 0; + draw_rects = 0; + draw_stipples = 0; + draw_fonts = 0; + break; + + case 'h': + usage(); + return 0; + break; + + case 'v': + printf("xdemo Ver 1.0\n"); + return 0; + break; + + case 'd': + if (sscanf(optarg, "%d", &g_delay_dur) != 1) { + fprintf(stderr, "\nerror: -d option requires an argument\n\n"); + usage(); + return -1; + } + break; + + case 'z': + if (strlen(optarg) <= 0) { + fprintf(stderr, "\nerror: invalid proxy application specified\n\n"); + usage(); + return -1; + } + strcpy(proxy_app, optarg); + printf("##### LK_TODO: proxy_app=%s\n", proxy_app); + zero_counters = 1; + break; + + case 'o': + if (strcmp(optarg, "jump") == 0) { + scroll_type = SCROLL_JUMP; + } + else if (strcmp(optarg, "smooth1") == 0) { + scroll_type = SCROLL_SMOOTH1; + } + else if (strcmp(optarg, "smooth2") == 0) { + scroll_type = SCROLL_SMOOTH2; + } + else { + fprintf(stderr, "\ninvalid scroll type specified\n\n"); + usage(); + return -1; + } + break; + + default: + usage(); + return -1; + } + } + + // must have at least one operation + if ((!draw_lines) && (!draw_rects) && (!draw_stipples) && + (!draw_fonts) && (!draw_image)) { + usage(); + return -1; + } + + g_disp = XOpenDisplay(NULL); + if (!g_disp) { + dprint("error opening X display\n"); + exit(-1); + } + + screenNumber = DefaultScreen(g_disp); + white = WhitePixel(g_disp, screenNumber); + black = BlackPixel(g_disp, screenNumber); + + g_win = XCreateSimpleWindow(g_disp, + DefaultRootWindow(g_disp), + 50, 50, // origin + g_winWidth, g_winHeight, // size + 0, black, // border + white ); // backgd + + XMapWindow(g_disp, g_win); + //eventMask = StructureNotifyMask | MapNotify | VisibilityChangeMask; + eventMask = StructureNotifyMask | VisibilityChangeMask; + XSelectInput(g_disp, g_win, eventMask); + + g_gc = XCreateGC(g_disp, g_win, + 0, // mask of values + NULL ); // array of values + #if 0 + do + { + dprint("about to call XNextEvent(...)\n"); + XNextEvent(g_disp, &evt);// calls XFlush + dprint("returned from XNextEvent(...)\n"); + } + //while(evt.type != MapNotify); + while(evt.type != VisibilityNotify); + #endif + + // get access to the screen's color map + colormap = DefaultColormap(g_disp, screenNumber); + + // alloc red color + rc = XAllocNamedColor(g_disp, colormap, "red", &g_colors[0], &g_colors[0]); + if (rc == 0) { + printf("XAllocNamedColor - failed to allocated 'red' color.\n"); + exit(1); + } + + rc = XAllocNamedColor(g_disp, colormap, "green", &g_colors[1], &g_colors[1]); + if (rc == 0) { + printf("XAllocNamedColor - failed to allocated 'green' color.\n"); + exit(1); + } + + rc = XAllocNamedColor(g_disp, colormap, "blue", &g_colors[2], &g_colors[2]); + if (rc == 0) { + printf("XAllocNamedColor - failed to allocated 'blue' color.\n"); + exit(1); + } + rc = XAllocNamedColor(g_disp, colormap, "yellow", &g_colors[3], &g_colors[3]); + if (rc == 0) { + printf("XAllocNamedColor - failed to allocated 'yellow' color.\n"); + exit(1); + } + rc = XAllocNamedColor(g_disp, colormap, "orange", &g_colors[4], &g_colors[4]); + if (rc == 0) { + printf("XAllocNamedColor - failed to allocated 'orange' color.\n"); + exit(1); + } + + if (zero_counters) { + signal_tcp_proxy(proxy_app); + } + + if (draw_lines) { + start_timer(&tv); + drawLines(iters); + printf("drew %d lines in %d ms\n", iters, time_elapsed_ms(tv)); + } + + if (draw_rects) { + start_timer(&tv); + drawRectangles(iters); + printf("drew %d rects in %d ms\n", iters, time_elapsed_ms(tv)); + } + + if (draw_stipples) { + start_timer(&tv); + // LK_TODO + } + + if (draw_fonts) { + start_timer(&tv); + drawFont(iters, msg); + printf("drew %d strings in %d ms\n", iters, time_elapsed_ms(tv)); + } + + if (draw_image) { + start_timer(&tv); + drawBMP(image_file, scroll_type); + printf("drew BMP in %d ms\n", time_elapsed_ms(tv)); + } + + if (zero_counters) { + signal_tcp_proxy(proxy_app); + } + + eventMask = ButtonPressMask|ButtonReleaseMask; + + XSelectInput(g_disp, g_win, eventMask); + + do + { + XNextEvent(g_disp, &evt); // calls XFlush() + } + while(evt.type != ButtonRelease); + + XDestroyWindow(g_disp, g_win); + XCloseDisplay(g_disp); + + return 0; +} + +int drawBMP(char *filename, int scroll_type) +{ + struct pic_info pic_info; + XImage *image; + Visual *visual; + Pixmap pixmap; + int depth; + int i; + int j; + + if (parse_bmp(filename, &pic_info) < 0) { + exit(-1); + } + XClearArea(g_disp, g_win, 0, 0, g_winWidth, g_winHeight, 0); + + depth = DefaultDepth(g_disp, DefaultScreen(g_disp)); + visual = DefaultVisual(g_disp, DefaultScreen(g_disp)); + + // create empty pixmap + pixmap = XCreatePixmap(g_disp, g_win, pic_info.width, pic_info.height, depth); + + // create an image from pixel data + image = XCreateImage(g_disp, visual, depth, ZPixmap, 0, pic_info.pixel_data, + pic_info.width, pic_info.height, 32, 0); + + if (pic_info.height <= g_winHeight) { + // image is too small to scroll + XFlush(g_disp); + XPutImage(g_disp, g_win, g_gc, image, 0, 0, 0, 0, pic_info.width, pic_info.height); + XFlush(g_disp); + return 0; + } + + if (scroll_type == SCROLL_JUMP) { + // copy image to pixelmap + XPutImage(g_disp, pixmap, g_gc, image, 0, 0, 0, 0, pic_info.width, pic_info.height); + + if (pic_info.height <= g_winHeight) { + // image too small - no scrolling required + XFlush(g_disp); + XCopyArea(g_disp, // connection to X server + pixmap, // source drawable + g_win, // dest drawable + g_gc, // graphics context + 0, 0, // source x,y + pic_info.width, // width + pic_info.height, // height + 0, 0); // dest x,y + XFlush(g_disp); + return 0; + } + + j = pic_info.height / g_winHeight; + if (pic_info.height % g_winHeight != 0) { + // need to include the last part of the image + j++; + } + XFlush(g_disp); + for (i = 0; i < j; i++) + { + XCopyArea(g_disp, // connection to X server + pixmap, // source drawable + g_win, // dest drawable + g_gc, // graphics context + 0, i * g_winHeight, // source x,y + pic_info.width, // width + pic_info.height, // height + 0, 0); // dest x,y + XFlush(g_disp); + sleep(3); + } + } + + /* + ** smooth scroll the image + */ + + // number of lines to be scrolled + j = pic_info.height - g_winHeight; + + if (scroll_type == SCROLL_SMOOTH1) { + XFlush(g_disp); + XPutImage(g_disp, g_win, g_gc, image, 0, 0, 0, 0, pic_info.width, pic_info.height); + XFlush(g_disp); + usleep(10000); + for (i = 0; i < j; i++) + { + XCopyArea(g_disp, g_win, g_win, g_gc, 0, 1, g_winWidth, g_winHeight - 1, 0, 0); + XPutImage(g_disp, g_win, g_gc, image, 0, g_winHeight + i, 0, g_winHeight -1 , pic_info.width, 1); + XFlush(g_disp); + usleep(10000); + } + return 0; + } + + if (scroll_type == SCROLL_SMOOTH2) { + XFlush(g_disp); + for (i = 0; i < j; i++) + { + XPutImage(g_disp, g_win, g_gc, image, 0, i, 0, 0, pic_info.width, pic_info.height - i); + XFlush(g_disp); + usleep(10000); + } + } + return 0; +} + +int process_bmp_event() +{ + XEvent ev; + long event_mask; + + event_mask = ExposureMask|ButtonPressMask|ButtonReleaseMask|StructureNotifyMask; + XSelectInput(g_disp, g_win, event_mask); + XNextEvent(g_disp, &ev); + switch(ev.type) + { + case Expose: + printf("got expose event\n"); + break; + + default: + printf("did not get expose event\n"); + break; + } + return 0; +} + +/** + * send a SIGUSR1 to process tcp_proxy, causing it to clear counters + * + * @return 0 on success, -1 on failure + */ + +int signal_tcp_proxy(char *proc_name) +{ + FILE *fp; + char *cptr; + char buf[2048]; + int pids[10]; + int status = 0; + int num_procs; + int i; + + sprintf(buf, "pidof %s", proc_name); + if ((fp = popen(buf, "r")) == NULL ) { + printf("xdemo: popen() failed\n"); + return -1; + } + + cptr = fgets(buf, 2047, fp); + if (cptr == NULL) { + pclose(fp); + return -1; + } + + num_procs = sscanf(buf, "%d %d %d %d %d %d %d %d %d %d", + &pids[0], &pids[1], &pids[2], &pids[3], &pids[4], + &pids[5], &pids[6], &pids[7], &pids[8], &pids[9]); + if (num_procs > 0) { + for (i = 0; i < num_procs; i++) { + kill(pids[i], SIGUSR1); + printf("sent SIGUSR1 to process %d\n", pids[i]); + } + } + + pclose(fp); + return status; +} + diff --git a/xorg/tests/xdemo/yosemite.bmp b/xorg/tests/xdemo/yosemite.bmp new file mode 100644 index 00000000..c64aba75 Binary files /dev/null and b/xorg/tests/xdemo/yosemite.bmp differ