Merge pull request #1815 from aquesnel/unify_logging_tests
Unify logging in tests/* (#1815)
This commit is contained in:
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 +0,0 @@
|
||||
!Makefile
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
EXTRA_DIST = \
|
||||
readme.txt
|
||||
|
||||
SUBDIRS = \
|
||||
memtest
|
||||
@@ -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
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
SUBDIRS = \
|
||||
devel
|
||||
@@ -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;
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user