Merge pull request #1815 from aquesnel/unify_logging_tests

Unify logging in tests/* (#1815)
This commit is contained in:
matt335672
2021-04-09 09:57:15 +01:00
committed by GitHub
27 changed files with 1097 additions and 1239 deletions
+5
View File
@@ -22,6 +22,7 @@ keygen/xrdp-keygen
.libs
libtool
*.lo
*.log
ltmain.sh
Makefile
Makefile.in
@@ -41,6 +42,10 @@ sesman/xrdp-sesman
sesman/sesman.ini
*.so
stamp-h1
test-driver
tests/memtest/memtest
tools/devel/tcp_proxy/tcp_proxy
*.trs
xrdp/xrdp
xrdp/xrdp.ini
xrdp_configure_options.h
+3 -2
View File
@@ -20,7 +20,6 @@ EXTRA_DIST = \
m4 \
postinstall-pak \
tcutils \
tests \
vrplayer
if XRDP_NEUTRINORDP
@@ -64,7 +63,9 @@ SUBDIRS = \
genkeymap \
xrdpapi \
pkgconfig \
$(XRDPVRDIR)
$(XRDPVRDIR) \
tests \
tools
distclean-local:
-rm -f xrdp_configure_options.h
+9 -1
View File
@@ -128,9 +128,17 @@ xrdp
├── mc ·········· media center module
├── neutrinordp · RDP client module for proxying RDP connections using NeutrinoRDP
├── pkgconfig ··· pkg-config configuration
├── sesman ······ session manager for xrdp
├── scripts ····· build scripts
├┬─ sesman ······ session manager for xrdp
|├── chansrv ···· channel server for xrdp
|├── libscp ····· authorization library
|└── tools ······ session management tools for sys admins
├── tcutils ····· QT based utility program for thin clients
├── tests ······· tests for the code
├┬─ tools ······· tools
|└┬─ devel ······ development tools
| ├── gtcp_proxy GTK app that forwards TCP connections to a remote host
| └── tcp_proxy · CLI app that forwards TCP connections to a remote host
├── vnc ········· VNC client module for xrdp
├── vrplayer ···· QT player redirecting video/audio to clients over xrdpvr channel
├── xrdp ········ main server code
+33 -119
View File
@@ -764,7 +764,18 @@ log_end(void)
}
/*****************************************************************************/
/* produce a hex dump */
/* log a hex dump */
enum logReturns
log_hexdump(const enum logLevels log_level,
const char *message,
const char *src,
int len)
{
return log_hexdump_with_location("", "", 0, log_level, message, src, len);
}
/*****************************************************************************/
/* log a hex dump */
enum logReturns
log_hexdump_with_location(const char *function_name,
const char *file_name,
@@ -774,38 +785,11 @@ log_hexdump_with_location(const char *function_name,
const char *src,
int len)
{
unsigned char *line;
int i;
int dump_number_lines;
int dump_line_length;
int dump_length;
int dump_offset;
int thisline;
int offset;
char *dump_buffer;
enum logReturns rv;
enum logReturns rv = LOG_STARTUP_OK;
enum logLevels override_log_level;
bool_t override_destination_level = 0;
/* Start the dump on a new line so that the first line of the dump is
aligned to the first column instead of to after the log message
preamble (eg. time, log level, ...)
*/
#define HEX_DUMP_SOURCE_BYTES_PER_LINE (16)
#ifdef _WIN32
#define HEX_DUMP_HEADER ("%s Hex Dump:\r\n")
#define HEX_DUMP_NEWLINE_SIZE (2)
#else
#ifdef _MACOS
#define HEX_DUMP_HEADER ("%s Hex Dump:\r")
#define HEX_DUMP_NEWLINE_SIZE (1)
#else
#define HEX_DUMP_HEADER ("%s Hex Dump:\n")
#define HEX_DUMP_NEWLINE_SIZE (1)
#endif
#endif
#define HEX_DUMP_HEADER_SIZE (sizeof(HEX_DUMP_HEADER) - 1)
override_destination_level = internal_log_location_overrides_level(
function_name,
file_name,
@@ -815,107 +799,37 @@ log_hexdump_with_location(const char *function_name,
return LOG_STARTUP_OK;
}
dump_line_length = (4 + 3 /* = 4 offset + 3 space */
+ ((2 + 1) * HEX_DUMP_SOURCE_BYTES_PER_LINE) /* + (2 hex char + 1 space) per source byte */
+ 2 /* + 2 space */
+ HEX_DUMP_SOURCE_BYTES_PER_LINE
+ HEX_DUMP_NEWLINE_SIZE);
dump_number_lines = (len / HEX_DUMP_SOURCE_BYTES_PER_LINE) + 1; /* +1 to round up */
dump_length = (dump_number_lines *dump_line_length /* hex dump lines */
+ HEX_DUMP_HEADER_SIZE
+ 1); /* terminating NULL */
dump_buffer = (char *)g_malloc(dump_length, 1);
if (dump_buffer == NULL)
{
LOG_DEVEL(LOG_LEVEL_WARNING,
"Failed to allocate buffer for hex dump of size %d",
dump_length);
return LOG_ERROR_MALLOC;
}
line = (unsigned char *)src;
offset = 0;
g_memcpy(dump_buffer, HEX_DUMP_HEADER, HEX_DUMP_HEADER_SIZE);
dump_offset = HEX_DUMP_HEADER_SIZE;
while (offset < len)
{
g_sprintf(dump_buffer + dump_offset, "%04x ", offset);
dump_offset += 7;
thisline = len - offset;
if (thisline > HEX_DUMP_SOURCE_BYTES_PER_LINE)
{
thisline = HEX_DUMP_SOURCE_BYTES_PER_LINE;
}
for (i = 0; i < thisline; i++)
{
g_sprintf(dump_buffer + dump_offset, "%02x ", line[i]);
dump_offset += 3;
}
for (; i < HEX_DUMP_SOURCE_BYTES_PER_LINE; i++)
{
dump_buffer[dump_offset++] = ' ';
dump_buffer[dump_offset++] = ' ';
dump_buffer[dump_offset++] = ' ';
}
dump_buffer[dump_offset++] = ' ';
dump_buffer[dump_offset++] = ' ';
for (i = 0; i < thisline; i++)
{
dump_buffer[dump_offset++] = (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.';
}
for (; i < HEX_DUMP_SOURCE_BYTES_PER_LINE; i++)
{
dump_buffer[dump_offset++] = ' ';
}
/* Start the dump on a new line so that the first line of the dump is
aligned to the first column instead of to after the log message
preamble (eg. time, log level, ...)
*/
#ifdef _WIN32
dump_buffer[dump_offset++] = '\r';
dump_buffer[dump_offset++] = '\n';
#define HEX_DUMP_HEADER ("Hex Dump:\r\n")
#else
#ifdef _MACOS
dump_buffer[dump_offset++] = '\r';
#define HEX_DUMP_HEADER ("Hex Dump:\r")
#else
dump_buffer[dump_offset++] = '\n';
#define HEX_DUMP_HEADER ("Hex Dump:\n")
#endif
#endif
offset += thisline;
line += thisline;
dump_buffer = g_bytes_to_hexdump(src, len);
if ((dump_offset - HEX_DUMP_HEADER_SIZE) % dump_line_length != 0)
{
LOG_DEVEL(LOG_LEVEL_ERROR,
"BUG: dump_offset (%d) at the end of a line is not a "
"multiple of the line length (%d)",
dump_offset, dump_line_length);
}
}
if (dump_offset > dump_length)
if (dump_buffer != NULL)
{
LOG_DEVEL(LOG_LEVEL_ERROR,
"BUG: dump_offset (%d) is larger than the dump_buffer length (%d)",
dump_offset, dump_length);
if (g_strlen(file_name) > 0)
{
rv = log_message_with_location(function_name, file_name, line_number,
log_level, "%s %s%s",
message, HEX_DUMP_HEADER, dump_buffer);
}
else
{
rv = log_message(log_level, "%s %s%s",
message, HEX_DUMP_HEADER, dump_buffer);
}
g_free(dump_buffer);
return LOG_GENERAL_ERROR;
}
/* replace the last new line with the end of the string since log_message
will add a new line */
dump_buffer[dump_offset - HEX_DUMP_NEWLINE_SIZE] = '\0';
rv = log_message_with_location(function_name, file_name, line_number,
log_level, dump_buffer, message);
g_free(dump_buffer);
return rv;
}
+21
View File
@@ -127,8 +127,23 @@ enum logReturns
#define LOG_DEVEL_HEXDUMP(log_level, message, buffer, length) \
log_hexdump_with_location(__func__, __FILE__, __LINE__, log_level, message, buffer, length)
/**
* @brief Logging macro for logging the contents of a byte array using a hex
* dump format.
*
* @param log_level, the log level
* @param message, a message prefix for the hex dump. Note: no printf like
* formatting is done to this message.
* @param buffer, a pointer to the byte array to log as a hex dump
* @param length, the length of the byte array to log
*/
#define LOG_HEXDUMP(log_level, message, buffer, length) \
log_hexdump_with_location(__func__, __FILE__, __LINE__, log_level, message, buffer, length)
#else
#define LOG(log_level, args...) log_message(log_level, args)
#define LOG_HEXDUMP(log_level, message, buffer, length) \
log_hexdump(log_level, message, buffer, length)
/* Since log_message() returns a value ensure that the elided versions of
* LOG_DEVEL and LOG_DEVEL_HEXDUMP also "fake" returning the success value
@@ -345,6 +360,12 @@ log_end(void);
enum logReturns
log_message(const enum logLevels lvl, const char *msg, ...) printflike(2, 3);
enum logReturns
log_hexdump(const enum logLevels log_level,
const char *msg,
const char *p,
int len);
/**
* the log function that all files use to log an event,
* with the function name and file line.
+125 -1
View File
@@ -25,8 +25,9 @@
#include <strings.h>
#include <stdlib.h>
#include "string_calls.h"
#include "log.h"
#include "os_calls.h"
#include "string_calls.h"
unsigned int
g_format_info_string(char *dest, unsigned int len,
@@ -470,6 +471,129 @@ g_bytes_to_hexstr(const void *bytes, int num_bytes, char *out_str,
return rv;
}
/*****************************************************************************/
/* convert a byte array into a hex dump */
char *
g_bytes_to_hexdump(const char *src, int len)
{
unsigned char *line;
int i;
int dump_number_lines;
int dump_line_length;
int dump_length;
int dump_offset;
int thisline;
int offset;
char *dump_buffer;
#define HEX_DUMP_SOURCE_BYTES_PER_LINE (16)
#ifdef _WIN32
#define HEX_DUMP_NEWLINE_SIZE (2)
#else
#ifdef _MACOS
#define HEX_DUMP_NEWLINE_SIZE (1)
#else
#define HEX_DUMP_NEWLINE_SIZE (1)
#endif
#endif
dump_line_length = (4 + 3 /* = 4 offset + 3 space */
+ ((2 + 1) * HEX_DUMP_SOURCE_BYTES_PER_LINE) /* + (2 hex char + 1 space) per source byte */
+ 2 /* + 2 space */
+ HEX_DUMP_SOURCE_BYTES_PER_LINE
+ HEX_DUMP_NEWLINE_SIZE);
dump_number_lines = (len / HEX_DUMP_SOURCE_BYTES_PER_LINE) + 1; /* +1 to round up */
dump_length = (dump_number_lines *dump_line_length /* hex dump lines */
+ 1); /* terminating NULL */
dump_buffer = (char *)g_malloc(dump_length, 1);
if (dump_buffer == NULL)
{
LOG_DEVEL(LOG_LEVEL_WARNING,
"Failed to allocate buffer for hex dump of size %d",
dump_length);
return NULL;
}
line = (unsigned char *)src;
offset = 0;
dump_offset = 0;
while (offset < len)
{
g_sprintf(dump_buffer + dump_offset, "%04x ", offset);
dump_offset += 7;
thisline = len - offset;
if (thisline > HEX_DUMP_SOURCE_BYTES_PER_LINE)
{
thisline = HEX_DUMP_SOURCE_BYTES_PER_LINE;
}
for (i = 0; i < thisline; i++)
{
g_sprintf(dump_buffer + dump_offset, "%02x ", line[i]);
dump_offset += 3;
}
for (; i < HEX_DUMP_SOURCE_BYTES_PER_LINE; i++)
{
dump_buffer[dump_offset++] = ' ';
dump_buffer[dump_offset++] = ' ';
dump_buffer[dump_offset++] = ' ';
}
dump_buffer[dump_offset++] = ' ';
dump_buffer[dump_offset++] = ' ';
for (i = 0; i < thisline; i++)
{
dump_buffer[dump_offset++] = (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.';
}
for (; i < HEX_DUMP_SOURCE_BYTES_PER_LINE; i++)
{
dump_buffer[dump_offset++] = ' ';
}
#ifdef _WIN32
dump_buffer[dump_offset++] = '\r';
dump_buffer[dump_offset++] = '\n';
#else
#ifdef _MACOS
dump_buffer[dump_offset++] = '\r';
#else
dump_buffer[dump_offset++] = '\n';
#endif
#endif
offset += thisline;
line += thisline;
if (dump_offset % dump_line_length != 0)
{
LOG_DEVEL(LOG_LEVEL_WARNING,
"BUG: dump_offset (%d) at the end of a line is not a "
"multiple of the line length (%d)",
dump_offset, dump_line_length);
}
}
if (dump_offset > dump_length)
{
LOG_DEVEL(LOG_LEVEL_WARNING,
"BUG: dump_offset (%d) is larger than the dump_buffer length (%d)",
dump_offset, dump_length);
dump_buffer[0] = '\0';
return dump_buffer;
}
/* replace the last new line with the end of the string since log_message
will add a new line */
dump_buffer[dump_offset - HEX_DUMP_NEWLINE_SIZE] = '\0';
return dump_buffer;
}
/*****************************************************************************/
int
g_pos(const char *str, const char *to_find)
+23
View File
@@ -80,6 +80,29 @@ g_bool2text(int value);
int
g_text2bool(const char *s);
/**
* Converts a binary array into a hux dump suitable for displaying to a user.
*
* The format of the hex dump is:
* 0000 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 ................
* /\ /\ /\
* | | |
* | | ascii representation of bytes
* | hex representation of bytes
* offset from beginning of the byte array in hex
*
* Note: the ascii representation uses '.' for all non-printable
* characters (eg. below 32 or above 127).
*
* Note: the string contains embedded new lines, but is not new line terminated.
*
* @param[in] src Value to convert
* @param[in] len The number of bytes in src to convert
* @return string containing the hex dump that must be free'd by the caller
*/
char *
g_bytes_to_hexdump(const char *src, int len);
int g_strlen(const char *text);
const char *g_strchr(const char *text, int c);
char *g_strcpy(char *dest, const char *src);
+5
View File
@@ -397,6 +397,11 @@ AC_CONFIG_FILES([
sesman/libscp/Makefile
sesman/Makefile
sesman/tools/Makefile
tests/Makefile
tests/memtest/Makefile
tools/Makefile
tools/devel/Makefile
tools/devel/tcp_proxy/Makefile
vnc/Makefile
xrdpapi/Makefile
xrdp/Makefile
-1
View File
@@ -1 +0,0 @@
!Makefile
+6
View File
@@ -0,0 +1,6 @@
EXTRA_DIST = \
readme.txt
SUBDIRS = \
memtest
-13
View File
@@ -1,13 +0,0 @@
OBJS = libmem.o memtest.o
#CFLAGS = -O2 -Wall
CFLAGS = -g
all: memtest
memtest: $(OBJS)
$(CC) -o memtest $(OBJS)
clean:
rm -f $(OBJS) librdp.a
+21
View File
@@ -0,0 +1,21 @@
AM_CPPFLAGS = \
-I$(top_srcdir)/common
if XRDP_DEBUG
AM_CPPFLAGS += -DXRDP_DEBUG
endif
sbin_PROGRAMS = \
memtest
memtest_SOURCES = \
libmem.h \
libmem.c \
memtest.c
memtest_LDADD = \
$(top_builddir)/common/libcommon.la
TESTS = \
memtest
+329 -332
View File
@@ -1,414 +1,411 @@
#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "log.h"
#define ALIGN_BY 32
#define ALIGN_BY_M1 (ALIGN_BY - 1)
#define ALIGN(_in) (((_in) + ALIGN_BY_M1) & (~ALIGN_BY_M1))
#define LLOG_LEVEL 1
#define LLOGLN(_log_level, _params) \
do { \
if (_log_level < LLOG_LEVEL) \
{ \
printf _params ; \
printf ("\n") ; \
} \
} while (0)
struct mem_item
{
unsigned int addr;
int bytes;
struct mem_item* next;
struct mem_item* prev;
unsigned int addr;
int bytes;
struct mem_item *next;
struct mem_item *prev;
};
struct mem_info
{
unsigned int addr;
int bytes;
int flags;
struct mem_item* free_head;
struct mem_item* free_tail;
struct mem_item* used_head;
struct mem_item* used_tail;
int total_bytes;
unsigned int addr;
int bytes;
int flags;
struct mem_item *free_head;
struct mem_item *free_tail;
struct mem_item *used_head;
struct mem_item *used_tail;
int total_bytes;
};
/*****************************************************************************/
static int
libmem_free_mem_item(struct mem_info* self, struct mem_item* mi)
libmem_free_mem_item(struct mem_info *self, struct mem_item *mi)
{
if (self == 0 || mi == 0)
{
if (self == 0 || mi == 0)
{
return 0;
}
if (mi->prev != 0)
{
mi->prev->next = mi->next;
}
if (mi->next != 0)
{
mi->next->prev = mi->prev;
}
if (mi == self->free_head)
{
self->free_head = mi->next;
}
if (mi == self->free_tail)
{
self->free_tail = mi->prev;
}
if (mi == self->used_head)
{
self->used_head = mi->next;
}
if (mi == self->used_tail)
{
self->used_tail = mi->prev;
}
free(mi);
return 0;
}
if (mi->prev != 0)
{
mi->prev->next = mi->next;
}
if (mi->next != 0)
{
mi->next->prev = mi->prev;
}
if (mi == self->free_head)
{
self->free_head = mi->next;
}
if (mi == self->free_tail)
{
self->free_tail = mi->prev;
}
if (mi == self->used_head)
{
self->used_head = mi->next;
}
if (mi == self->used_tail)
{
self->used_tail = mi->prev;
}
free(mi);
return 0;
}
/*****************************************************************************/
void*
void *
libmem_init(unsigned int addr, int bytes)
{
struct mem_info* self;
struct mem_item* mi;
struct mem_info *self;
struct mem_item *mi;
self = (struct mem_info*)malloc(sizeof(struct mem_info));
memset(self, 0, sizeof(struct mem_info));
self->addr = addr;
self->bytes = bytes;
//self->flags = 1;
mi = (struct mem_item*)malloc(sizeof(struct mem_item));
memset(mi, 0, sizeof(struct mem_item));
mi->addr = addr;
mi->bytes = bytes;
self->free_head = mi;
self->free_tail = mi;
return self;
self = (struct mem_info *)malloc(sizeof(struct mem_info));
memset(self, 0, sizeof(struct mem_info));
self->addr = addr;
self->bytes = bytes;
//self->flags = 1;
mi = (struct mem_item *)malloc(sizeof(struct mem_item));
memset(mi, 0, sizeof(struct mem_item));
mi->addr = addr;
mi->bytes = bytes;
self->free_head = mi;
self->free_tail = mi;
return self;
}
/*****************************************************************************/
void
libmem_deinit(void* aself)
libmem_deinit(void *aself)
{
struct mem_info* self;
struct mem_info *self;
self = (struct mem_info*)aself;
if (self == 0)
{
return;
}
while (self->free_head != 0)
{
libmem_free_mem_item(self, self->free_head);
}
while (self->used_head != 0)
{
libmem_free_mem_item(self, self->used_head);
}
free(self);
self = (struct mem_info *)aself;
if (self == 0)
{
return;
}
while (self->free_head != 0)
{
libmem_free_mem_item(self, self->free_head);
}
while (self->used_head != 0)
{
libmem_free_mem_item(self, self->used_head);
}
free(self);
}
/****************************************************************************/
static int
libmem_add_used_item(struct mem_info* self, unsigned int addr, int bytes)
libmem_add_used_item(struct mem_info *self, unsigned int addr, int bytes)
{
struct mem_item* mi;
struct mem_item* new_mi;
int added;
struct mem_item *mi;
struct mem_item *new_mi;
int added;
if (self == 0 || addr == 0)
{
return 1;
}
if (self->used_head == 0)
{
/* add first item */
new_mi = (struct mem_item*)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
self->used_head = new_mi;
self->used_tail = new_mi;
return 0;
}
added = 0;
mi = self->used_head;
while (mi != 0)
{
if (mi->addr > addr)
if (self == 0 || addr == 0)
{
/* add before */
new_mi = (struct mem_item*)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
new_mi->prev = mi->prev;
new_mi->next = mi;
if (mi->prev != 0)
{
mi->prev->next = new_mi;
}
mi->prev = new_mi;
if (self->used_head == mi)
{
return 1;
}
if (self->used_head == 0)
{
/* add first item */
new_mi = (struct mem_item *)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
self->used_head = new_mi;
}
added = 1;
break;
self->used_tail = new_mi;
return 0;
}
mi = mi->next;
}
if (!added)
{
/* add last */
new_mi = (struct mem_item*)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
self->used_tail->next = new_mi;
new_mi->prev = self->used_tail;
self->used_tail = new_mi;
}
return 0;
added = 0;
mi = self->used_head;
while (mi != 0)
{
if (mi->addr > addr)
{
/* add before */
new_mi = (struct mem_item *)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
new_mi->prev = mi->prev;
new_mi->next = mi;
if (mi->prev != 0)
{
mi->prev->next = new_mi;
}
mi->prev = new_mi;
if (self->used_head == mi)
{
self->used_head = new_mi;
}
added = 1;
break;
}
mi = mi->next;
}
if (!added)
{
/* add last */
new_mi = (struct mem_item *)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
self->used_tail->next = new_mi;
new_mi->prev = self->used_tail;
self->used_tail = new_mi;
}
return 0;
}
/****************************************************************************/
static int
libmem_add_free_item(struct mem_info* self, unsigned int addr, int bytes)
libmem_add_free_item(struct mem_info *self, unsigned int addr, int bytes)
{
struct mem_item* mi;
struct mem_item* new_mi;
int added;
struct mem_item *mi;
struct mem_item *new_mi;
int added;
if (self == 0 || addr == 0)
{
return 1;
}
if (self->free_head == 0)
{
/* add first item */
new_mi = (struct mem_item*)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
self->free_head = new_mi;
self->free_tail = new_mi;
return 0;
}
added = 0;
mi = self->free_head;
while (mi != 0)
{
if (mi->addr > addr)
if (self == 0 || addr == 0)
{
if (mi->prev != 0)
{
if (mi->prev->addr + mi->prev->bytes == addr)
{
/* don't need to add, just make prev bigger */
mi->prev->bytes += bytes;
if (mi->prev->addr + mi->prev->bytes == mi->addr)
{
/* here we can remove one */
mi->prev->bytes += mi->bytes;
libmem_free_mem_item(self, mi);
}
return 0;
}
}
if (addr + bytes == mi->addr)
{
/* don't need to add here either */
mi->addr = addr;
mi->bytes += bytes;
return 0;
}
/* add before */
new_mi = (struct mem_item*)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
new_mi->prev = mi->prev;
new_mi->next = mi;
if (mi->prev != 0)
{
mi->prev->next = new_mi;
}
mi->prev = new_mi;
if (self->free_head == mi)
{
self->free_head = new_mi;
}
added = 1;
break;
return 1;
}
mi = mi->next;
}
if (!added)
{
/* add last */
new_mi = (struct mem_item*)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
self->free_tail->next = new_mi;
new_mi->prev = self->free_tail;
self->free_tail = new_mi;
}
return 0;
if (self->free_head == 0)
{
/* add first item */
new_mi = (struct mem_item *)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
self->free_head = new_mi;
self->free_tail = new_mi;
return 0;
}
added = 0;
mi = self->free_head;
while (mi != 0)
{
if (mi->addr > addr)
{
if (mi->prev != 0)
{
if (mi->prev->addr + mi->prev->bytes == addr)
{
/* don't need to add, just make prev bigger */
mi->prev->bytes += bytes;
if (mi->prev->addr + mi->prev->bytes == mi->addr)
{
/* here we can remove one */
mi->prev->bytes += mi->bytes;
libmem_free_mem_item(self, mi);
}
return 0;
}
}
if (addr + bytes == mi->addr)
{
/* don't need to add here either */
mi->addr = addr;
mi->bytes += bytes;
return 0;
}
/* add before */
new_mi = (struct mem_item *)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
new_mi->prev = mi->prev;
new_mi->next = mi;
if (mi->prev != 0)
{
mi->prev->next = new_mi;
}
mi->prev = new_mi;
if (self->free_head == mi)
{
self->free_head = new_mi;
}
added = 1;
break;
}
mi = mi->next;
}
if (!added)
{
/* add last */
new_mi = (struct mem_item *)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
self->free_tail->next = new_mi;
new_mi->prev = self->free_tail;
self->free_tail = new_mi;
}
return 0;
}
/*****************************************************************************/
static int
libmem_print(struct mem_info* self)
libmem_print(struct mem_info *self)
{
struct mem_item* mi;
struct mem_item *mi;
LLOGLN(0, ("libmem_print:"));
LLOGLN(0, (" used_head %p", self->used_head));
LLOGLN(0, (" used_tail %p", self->used_tail));
mi = self->used_head;
if (mi != 0)
{
LLOGLN(0, (" used list"));
while (mi != 0)
LOG_DEVEL(LOG_LEVEL_DEBUG, "libmem_print:");
LOG_DEVEL(LOG_LEVEL_DEBUG, " used_head %p", self->used_head);
LOG_DEVEL(LOG_LEVEL_DEBUG, " used_tail %p", self->used_tail);
mi = self->used_head;
if (mi != 0)
{
LLOGLN(0, (" ptr %p prev %p next %p addr 0x%8.8x bytes %d",
mi, mi->prev, mi->next, mi->addr, mi->bytes));
mi = mi->next;
LOG_DEVEL(LOG_LEVEL_DEBUG, " used list");
while (mi != 0)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, " ptr %p prev %p next %p addr 0x%8.8x bytes %d",
mi, mi->prev, mi->next, mi->addr, mi->bytes);
mi = mi->next;
}
}
}
LLOGLN(0, (" free_head %p", self->free_head));
LLOGLN(0, (" free_tail %p", self->free_tail));
mi = self->free_head;
if (mi != 0)
{
LLOGLN(0, (" free list"));
while (mi != 0)
LOG_DEVEL(LOG_LEVEL_DEBUG, " free_head %p", self->free_head);
LOG_DEVEL(LOG_LEVEL_DEBUG, " free_tail %p", self->free_tail);
mi = self->free_head;
if (mi != 0)
{
LLOGLN(0, (" ptr %p prev %p next %p addr 0x%8.8x bytes %d",
mi, mi->prev, mi->next, mi->addr, mi->bytes));
mi = mi->next;
LOG_DEVEL(LOG_LEVEL_DEBUG, " free list");
while (mi != 0)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, " ptr %p prev %p next %p addr 0x%8.8x bytes %d",
mi, mi->prev, mi->next, mi->addr, mi->bytes);
mi = mi->next;
}
}
}
return 0;
return 0;
}
/*****************************************************************************/
unsigned int
libmem_alloc(void* obj, int bytes)
libmem_alloc(void *obj, int bytes)
{
struct mem_info* self;
struct mem_item* mi;
unsigned int addr;
struct mem_info *self;
struct mem_item *mi;
unsigned int addr;
if (bytes < 1)
{
if (bytes < 1)
{
return 0;
}
bytes = ALIGN(bytes);
self = (struct mem_info *)obj;
addr = 0;
mi = self->free_head;
while (mi != 0)
{
if (bytes <= mi->bytes)
{
addr = mi->addr;
mi->bytes -= bytes;
mi->addr += bytes;
if (mi->bytes < 1)
{
libmem_free_mem_item(self, mi);
}
break;
}
mi = mi->next;
}
if (addr != 0)
{
self->total_bytes += bytes;
libmem_add_used_item(self, addr, bytes);
if (self->flags & 1)
{
libmem_print(self);
}
}
else
{
LOG_DEVEL(LOG_LEVEL_ERROR, "libmem_alloc: error");
}
return addr;
}
/*****************************************************************************/
int
libmem_free(void *obj, unsigned int addr)
{
struct mem_info *self;
struct mem_item *mi;
if (addr == 0)
{
return 0;
}
self = (struct mem_info *)obj;
mi = self->used_tail;
while (mi != 0)
{
if (mi->addr == addr)
{
self->total_bytes -= mi->bytes;
libmem_add_free_item(self, mi->addr, mi->bytes);
libmem_free_mem_item(self, mi);
if (self->flags & 1)
{
libmem_print(self);
}
return 0;
}
mi = mi->prev;
}
LOG_DEVEL(LOG_LEVEL_ERROR, "libmem_free: error");
return 1;
}
/*****************************************************************************/
int
libmem_set_flags(void *obj, int flags)
{
struct mem_info *self;
self = (struct mem_info *)obj;
self->flags |= flags;
return 0;
}
bytes = ALIGN(bytes);
self = (struct mem_info*)obj;
addr = 0;
mi = self->free_head;
while (mi != 0)
{
if (bytes <= mi->bytes)
{
addr = mi->addr;
mi->bytes -= bytes;
mi->addr += bytes;
if (mi->bytes < 1)
{
libmem_free_mem_item(self, mi);
}
break;
}
mi = mi->next;
}
if (addr != 0)
{
self->total_bytes += bytes;
libmem_add_used_item(self, addr, bytes);
if (self->flags & 1)
{
libmem_print(self);
}
}
else
{
LLOGLN(0, ("libmem_alloc: error"));
}
return addr;
}
/*****************************************************************************/
int
libmem_free(void* obj, unsigned int addr)
libmem_clear_flags(void *obj, int flags)
{
struct mem_info* self;
struct mem_item* mi;
struct mem_info *self;
if (addr == 0)
{
self = (struct mem_info *)obj;
self->flags &= ~flags;
return 0;
}
self = (struct mem_info*)obj;
mi = self->used_tail;
while (mi != 0)
{
if (mi->addr == addr)
{
self->total_bytes -= mi->bytes;
libmem_add_free_item(self, mi->addr, mi->bytes);
libmem_free_mem_item(self, mi);
if (self->flags & 1)
{
libmem_print(self);
}
return 0;
}
mi = mi->prev;
}
LLOGLN(0, ("libmem_free: error"));
return 1;
}
/*****************************************************************************/
int
libmem_set_flags(void* obj, int flags)
libmem_get_alloced_bytes(void *obj)
{
struct mem_info* self;
struct mem_info *self;
self = (struct mem_info*)obj;
self->flags |= flags;
return 0;
}
/*****************************************************************************/
int
libmem_clear_flags(void* obj, int flags)
{
struct mem_info* self;
self = (struct mem_info*)obj;
self->flags &= ~flags;
return 0;
}
/*****************************************************************************/
int
libmem_get_alloced_bytes(void* obj)
{
struct mem_info* self;
self = (struct mem_info*)obj;
return self->total_bytes;
self = (struct mem_info *)obj;
return self->total_bytes;
}
+7 -7
View File
@@ -2,19 +2,19 @@
#ifndef _LIBMEM_C
#define _LIBMEM_C
void*
void *
libmem_init(unsigned int addr, int bytes);
void
libmem_deinit(void* aself);
libmem_deinit(void *aself);
unsigned int
libmem_alloc(void* obj, int bytes);
libmem_alloc(void *obj, int bytes);
int
libmem_free(void* obj, unsigned int addr);
libmem_free(void *obj, unsigned int addr);
int
libmem_set_flags(void* obj, int flags);
libmem_set_flags(void *obj, int flags);
int
libmem_clear_flags(void* obj, int flags);
libmem_clear_flags(void *obj, int flags);
int
libmem_get_alloced_bytes(void* obj);
libmem_get_alloced_bytes(void *obj);
#endif
+60 -48
View File
@@ -1,60 +1,72 @@
#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "libmem.h"
#include "log.h"
int main(int argc, char** argv)
int main(int argc, char **argv)
{
void* obj;
unsigned int addr1;
unsigned int addr2;
unsigned int addr3;
unsigned int addr4;
unsigned int addr5;
int index;
int rd;
void *obj;
unsigned int addr1;
unsigned int addr2;
unsigned int addr3;
unsigned int addr4;
unsigned int addr5;
int index;
int rd;
struct log_config *config;
srand(time(0));
obj = libmem_init(0x80000000, 64 * 1024 * 1024);
for (index = 0; index < 256; index++)
{
rd = rand() & 0xffff;
printf("1 rd %d\n", rd);
addr1 = libmem_alloc(obj, rd);
rd = rand() & 0xffff;
printf("2 rd %d\n", rd);
addr2 = libmem_alloc(obj, rd);
rd = rand() & 0xffff;
printf("3 rd %d\n", rd);
addr3 = libmem_alloc(obj, rd);
rd = rand() & 0xffff;
printf("4 rd %d\n", rd);
addr4 = libmem_alloc(obj, rd);
addr5 = libmem_alloc(obj, rd);
libmem_free(obj, addr1);
printf("5\n");
addr1 = libmem_alloc(obj, 64);
printf("6\n");
libmem_free(obj, addr3);
printf("7\n");
addr3 = libmem_alloc(obj, 64 * 1024);
libmem_free(obj, addr5);
addr5 = libmem_alloc(obj, 64 * 1024);
printf("8\n");
libmem_free(obj, addr1);
printf("9\n");
libmem_free(obj, addr2);
printf("10\n");
libmem_free(obj, addr3);
libmem_free(obj, addr4);
if (index == 255)
config = log_config_init_for_console(LOG_LEVEL_DEBUG, NULL);
log_start_from_param(config);
log_config_free(config);
srand(time(0));
obj = libmem_init(0x80000000, 64 * 1024 * 1024);
for (index = 0; index < 256; index++)
{
libmem_set_flags(obj, 1);
rd = rand() & 0xffff;
printf("1 rd %d\n", rd);
addr1 = libmem_alloc(obj, rd);
rd = rand() & 0xffff;
printf("2 rd %d\n", rd);
addr2 = libmem_alloc(obj, rd);
rd = rand() & 0xffff;
printf("3 rd %d\n", rd);
addr3 = libmem_alloc(obj, rd);
rd = rand() & 0xffff;
printf("4 rd %d\n", rd);
addr4 = libmem_alloc(obj, rd);
addr5 = libmem_alloc(obj, rd);
libmem_free(obj, addr1);
printf("5\n");
addr1 = libmem_alloc(obj, 64);
printf("6\n");
libmem_free(obj, addr3);
printf("7\n");
addr3 = libmem_alloc(obj, 64 * 1024);
libmem_free(obj, addr5);
addr5 = libmem_alloc(obj, 64 * 1024);
printf("8\n");
libmem_free(obj, addr1);
printf("9\n");
libmem_free(obj, addr2);
printf("10\n");
libmem_free(obj, addr3);
libmem_free(obj, addr4);
if (index == 255)
{
libmem_set_flags(obj, 1);
}
libmem_free(obj, addr5);
}
libmem_free(obj, addr5);
}
libmem_deinit(obj);
return 0;
libmem_deinit(obj);
log_end();
return 0;
}
-13
View File
@@ -1,13 +0,0 @@
CFLAGS = -O2 -Wall
LDFLAGS =
OBJS = main.o
LIBS = -ldl
all: tcp_proxy
tcp_proxy: $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o tcp_proxy $(OBJS) $(LIBS)
.PHONY clean:
rm -f $(OBJS) tcp_proxy
-701
View File
@@ -1,701 +0,0 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2014
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <locale.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.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];
typedef unsigned short tui16;
/*****************************************************************************/
static void
g_memset(void *ptr, int val, int size)
{
memset(ptr, val, size);
}
/*****************************************************************************/
static void
g_printf(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vfprintf(stdout, format, ap);
va_end(ap);
}
/*****************************************************************************/
static void
g_writeln(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vfprintf(stdout, format, ap);
va_end(ap);
g_printf("\n");
}
/*****************************************************************************/
static void
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("%s", "");
offset += thisline;
line += thisline;
}
}
/*****************************************************************************/
static int
g_tcp_socket(void)
{
int rv;
int option_value;
socklen_t option_len;
rv = (int)socket(AF_INET, SOCK_STREAM, 0);
if (rv < 0)
{
return -1;
}
option_len = sizeof(option_value);
if (getsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (char *)&option_value,
&option_len) == 0)
{
if (option_value == 0)
{
option_value = 1;
option_len = sizeof(option_value);
setsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (char *)&option_value,
option_len);
}
}
option_len = sizeof(option_value);
if (getsockopt(rv, SOL_SOCKET, SO_SNDBUF, (char *)&option_value,
&option_len) == 0)
{
if (option_value < (1024 * 32))
{
option_value = 1024 * 32;
option_len = sizeof(option_value);
setsockopt(rv, SOL_SOCKET, SO_SNDBUF, (char *)&option_value,
option_len);
}
}
return rv;
}
/*****************************************************************************/
static int
g_tcp_set_non_blocking(int sck)
{
unsigned long i;
i = fcntl(sck, F_GETFL);
i = i | O_NONBLOCK;
fcntl(sck, F_SETFL, i);
return 0;
}
/*****************************************************************************/
static int
g_tcp_bind(int sck, const char* port)
{
struct sockaddr_in s;
memset(&s, 0, sizeof(struct sockaddr_in));
s.sin_family = AF_INET;
s.sin_port = htons((tui16)atoi(port));
s.sin_addr.s_addr = INADDR_ANY;
return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in));
}
/*****************************************************************************/
static int
g_tcp_listen(int sck)
{
return listen(sck, 2);
}
/*****************************************************************************/
static int
g_tcp_select(int sck1, int sck2)
{
fd_set rfds;
struct timeval time;
int max = 0;
int rv = 0;
g_memset(&rfds, 0, sizeof(fd_set));
g_memset(&time, 0, sizeof(struct timeval));
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;
}
/*****************************************************************************/
static int
g_tcp_recv(int sck, void *ptr, int len, int flags)
{
return recv(sck, ptr, len, flags);
}
/*****************************************************************************/
static void
g_tcp_close(int sck)
{
if (sck == 0)
{
return;
}
close(sck);
}
/*****************************************************************************/
static int
g_tcp_send(int sck, const void *ptr, int len, int flags)
{
return send(sck, ptr, len, flags);
}
/*****************************************************************************/
void
g_sleep(int msecs)
{
usleep(msecs * 1000);
}
/*****************************************************************************/
static int
g_tcp_last_error_would_block(int sck)
{
return (errno == EWOULDBLOCK) || (errno == EAGAIN) || (errno == EINPROGRESS);
}
/*****************************************************************************/
static int
g_tcp_accept(int sck)
{
int ret ;
struct sockaddr_in s;
unsigned int i;
i = sizeof(struct sockaddr_in);
memset(&s, 0, i);
ret = accept(sck, (struct sockaddr *)&s, &i);
return ret ;
}
/*****************************************************************************/
static int
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((tui16)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));
}
/*****************************************************************************/
static int
g_tcp_socket_ok(int sck)
{
int opt;
socklen_t opt_len = sizeof(opt);
if (getsockopt(sck, SOL_SOCKET, SO_ERROR, (char *)(&opt), &opt_len) == 0)
{
if (opt == 0)
{
return 1;
}
}
return 0;
}
/*****************************************************************************/
static void
g_init(const char *app_name)
{
setlocale(LC_CTYPE, "");
}
/*****************************************************************************/
static void
g_deinit(void)
{
}
/*****************************************************************************/
static int
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 g_tcp_socket_ok(sck);
}
}
return 0;
}
/*****************************************************************************/
static void
g_signal_user_interrupt(void (*func)(int))
{
signal(SIGINT, func);
}
/*****************************************************************************/
static void
g_signal_terminate(void (*func)(int))
{
signal(SIGTERM, func);
}
/*****************************************************************************/
static void
g_signal_usr1(void (*func)(int))
{
signal(SIGUSR1, func);
}
/*****************************************************************************/
static int
g_strcasecmp(const char *c1, const char *c2)
{
return strcasecmp(c1, c2);
}
/*****************************************************************************/
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 incoming connection */
if (error == 0)
{
error = g_tcp_listen(lis_sck);
if (error == 0)
{
g_writeln("listening for connection");
}
}
/* accept an incoming 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("timeout 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 <local-port> <remote-ip> <remote-port> [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("tcp_proxy");
g_signal_user_interrupt(proxy_shutdown); /* SIGINT */
g_signal_usr1(clear_counters); /* SIGUSR1 */
g_signal_terminate(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;
}
+3
View File
@@ -0,0 +1,3 @@
SUBDIRS = \
devel
+6
View File
@@ -0,0 +1,6 @@
EXTRA_DIST = \
gtcp_proxy
SUBDIRS = \
tcp_proxy
@@ -332,7 +332,9 @@ static void *tcp_proxy(void *arg)
for (i = 0; i < 100; i++)
{
if (tcp_can_send(con_skt, 100))
{
break;
}
usleep(100);
}
@@ -452,7 +454,9 @@ static void show_msg(int not_main_window, int style,
GtkWidget *dialog;
if (not_main_window)
{
gdk_threads_enter();
}
dialog = gtk_message_dialog_new(GTK_WINDOW(NULL),
GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -465,7 +469,9 @@ static void show_msg(int not_main_window, int style,
gtk_widget_destroy(dialog);
if (not_main_window)
{
gdk_threads_leave();
}
}
/**
@@ -475,12 +481,16 @@ static void show_msg(int not_main_window, int style,
static void show_status(int not_main_thread, char *msg)
{
if (not_main_thread)
{
gdk_threads_enter();
}
gtk_statusbar_push(GTK_STATUSBAR(g_statusbar), CONTEXT_ID, msg);
if (not_main_thread)
{
gdk_threads_leave();
}
}
/**
@@ -490,12 +500,16 @@ static void show_status(int not_main_thread, char *msg)
static void clear_status(int not_main_thread)
{
if (not_main_thread)
{
gdk_threads_enter();
}
gtk_statusbar_remove_all(GTK_STATUSBAR(g_statusbar), CONTEXT_ID);
if (not_main_thread)
{
gdk_threads_leave();
}
}
/**
@@ -505,12 +519,16 @@ static void clear_status(int not_main_thread)
static void enable_btn_start(int not_main_thread)
{
if (not_main_thread)
{
gdk_threads_enter();
}
gtk_widget_set_sensitive(GTK_WIDGET(g_btn_start), TRUE);
if (not_main_thread)
{
gdk_threads_leave();
}
}
/**
@@ -520,12 +538,16 @@ static void enable_btn_start(int not_main_thread)
static void disable_btn_start(int not_main_thread)
{
if (not_main_thread)
{
gdk_threads_enter();
}
gtk_widget_set_sensitive(GTK_WIDGET(g_btn_start), FALSE);
if (not_main_thread)
{
gdk_threads_leave();
}
}
/**
@@ -569,12 +591,16 @@ static void show_loc_port_stats(int not_main_thread, int count)
sprintf(buf, "%d", count);
if (not_main_thread)
{
gdk_threads_enter();
}
gtk_entry_set_text(GTK_ENTRY(g_tbx_loc_stats), buf);
if (not_main_thread)
{
gdk_threads_leave();
}
}
/**
@@ -588,12 +614,16 @@ static void show_rem_port_stats(int not_main_thread, int count)
sprintf(buf, "%d", count);
if (not_main_thread)
{
gdk_threads_enter();
}
gtk_entry_set_text(GTK_ENTRY(g_tbx_rem_stats), buf);
if (not_main_thread)
{
gdk_threads_leave();
}
}
/**
@@ -30,7 +30,9 @@ int tcp_socket_create(void)
/* in win32 a socket is an unsigned int, in linux, it's an int */
if ((rv = (int) socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
return -1;
}
option_len = sizeof(option_value);
@@ -157,7 +159,9 @@ int tcp_last_error_would_block()
void tcp_close(int skt)
{
if (skt <= 0)
{
return;
}
#if defined(_WIN32)
closesocket(skt);
@@ -180,7 +184,9 @@ int tcp_socket(void)
/* in win32 a socket is an unsigned int, in linux, it's an int */
if ((rv = (int) socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
return -1;
}
option_len = sizeof(option_value);
@@ -295,7 +301,9 @@ int tcp_socket_ok(int skt)
if (getsockopt(skt, SOL_SOCKET, SO_ERROR, (char *) (&opt), &opt_len) == 0)
{
if (opt == 0)
{
return 1;
}
}
return 0;
@@ -323,15 +331,21 @@ int tcp_select(int sck1, int sck2)
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);
@@ -340,10 +354,14 @@ int tcp_select(int sck1, int sck2)
rv = 0;
if (FD_ISSET(((unsigned int) sck1), &rfds))
{
rv = rv | 1;
}
if (FD_ISSET(((unsigned int)sck2), &rfds))
{
rv = rv | 2;
}
}
else
{
@@ -43,10 +43,13 @@ void hexdump(int address, char *buf, int len)
unsigned char c;
char cvt[] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
if ((buf == NULL) || (len <= 0))
{
return;
}
addr = (address < 0) ? 0 : address;
blocks = len / 16;
@@ -85,9 +88,13 @@ void hexdump(int address, char *buf, int len)
outbuf[index2++] = ' ';
if ((c >= 0x20) && (c <= 0x7e))
{
outbuf[index3++] = c;
}
else
{
outbuf[index3++] = '.';
}
}
outbuf[index3] = 0;
@@ -95,7 +102,9 @@ void hexdump(int address, char *buf, int len)
}
if (!residual)
{
return;
}
outbuf[7] = cvt[(addr >> 0) & 0x0000000f];
outbuf[6] = cvt[(addr >> 4) & 0x0000000f];
@@ -120,9 +129,13 @@ void hexdump(int address, char *buf, int len)
outbuf[index2++] = ' ';
if ((c >= 0x20) && (c <= 0x7e))
{
outbuf[index3++] = c;
}
else
{
outbuf[index3++] = '.';
}
}
outbuf[index3] = 0;
+17
View File
@@ -0,0 +1,17 @@
AM_CPPFLAGS = \
-I$(top_srcdir)/common
if XRDP_DEBUG
AM_CPPFLAGS += -DXRDP_DEBUG
endif
sbin_PROGRAMS = \
tcp_proxy
tcp_proxy_SOURCES = \
main.c
tcp_proxy_LDADD = \
$(top_builddir)/common/libcommon.la \
-ldl
+362
View File
@@ -0,0 +1,362 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2014
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <locale.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "log.h"
#include "os_calls.h"
#include "string_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];
typedef unsigned short tui16;
/*****************************************************************************/
static int
g_tcp_socket_ok(int sck)
{
int opt;
socklen_t opt_len = sizeof(opt);
if (getsockopt(sck, SOL_SOCKET, SO_ERROR, (char *)(&opt), &opt_len) == 0)
{
if (opt == 0)
{
return 1;
}
}
return 0;
}
/*****************************************************************************/
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)
{
LOG(LOG_LEVEL_WARNING, "bind failed");
}
/* listen for an incoming connection */
if (error == 0)
{
error = g_tcp_listen(lis_sck);
if (error == 0)
{
LOG(LOG_LEVEL_INFO, "listening for connection");
}
}
/* accept an incoming 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)
{
LOG(LOG_LEVEL_INFO, "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_tcp_socket_ok(con_sck))
&& (!g_terminated)
&& (i < 100))
{
g_sleep(100);
i++;
}
if (i > 99)
{
LOG(LOG_LEVEL_ERROR, "timeout connecting");
error = 1;
}
if (g_terminated)
{
error = 1;
}
}
if ((error != 0) && (!g_terminated))
{
LOG(LOG_LEVEL_ERROR, "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)
{
LOG_HEXDUMP(LOG_LEVEL_INFO, "from remove, the socket from connect", g_buf, count);
}
LOG(LOG_LEVEL_DEBUG, "local_io_count: %d\tremote_io_count: %d",
g_loc_io_count, g_rem_io_count);
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))
{
if (g_tcp_can_send(acc_sck, 1000))
{
g_tcp_socket_ok(acc_sck);
}
}
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)
{
LOG_HEXDUMP(LOG_LEVEL_INFO, "from accepted, the socket from accept", g_buf, count);
}
LOG(LOG_LEVEL_DEBUG, "local_io_count: %d\tremote_io_count: %d",
g_loc_io_count, g_rem_io_count);
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))
{
if (g_tcp_can_send(con_sck, 1000))
{
g_tcp_socket_ok(con_sck);
}
}
else if (i < 1)
{
error = 1;
}
else
{
sent += i;
}
}
}
}
}
g_tcp_close(lis_sck);
g_tcp_close(con_sck);
g_tcp_close(acc_sck);
LOG(LOG_LEVEL_INFO, "acc_to_con %d", acc_to_con);
LOG(LOG_LEVEL_INFO, "con_to_acc %d", con_to_acc);
return 0;
}
/*****************************************************************************/
static int
usage(void)
{
g_writeln("tcp_proxy <local-port> <remote-ip> <remote-port> [dump]");
return 0;
}
/*****************************************************************************/
void
proxy_shutdown(int sig)
{
LOG(LOG_LEVEL_INFO, "shutting down");
g_terminated = 1;
}
void
clear_counters(int sig)
{
LOG(LOG_LEVEL_DEBUG, "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;
struct log_config *config;
if (argc < 4)
{
usage();
return 0;
}
g_init("tcp_proxy");
g_signal_user_interrupt(proxy_shutdown); /* SIGINT */
g_signal_usr1(clear_counters); /* SIGUSR1 */
g_signal_terminate(proxy_shutdown); /* SIGTERM */
config = log_config_init_for_console(LOG_LEVEL_INFO, NULL);
log_start_from_param(config);
log_config_free(config);
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);
}
}
log_end();
g_deinit();
return 0;
}