[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r31834 - in gnunet/src: conversation util
From: |
gnunet |
Subject: |
[GNUnet-SVN] r31834 - in gnunet/src: conversation util |
Date: |
Wed, 8 Jan 2014 15:14:41 +0100 |
Author: LRN
Date: 2014-01-08 15:14:41 +0100 (Wed, 08 Jan 2014)
New Revision: 31834
Added:
gnunet/src/util/gnunet-helper-w32-console.c
gnunet/src/util/gnunet-helper-w32-console.h
Modified:
gnunet/src/conversation/gnunet-conversation.c
gnunet/src/util/Makefile.am
Log:
Add console hackery for gnunet-conversation on W32
Modified: gnunet/src/conversation/gnunet-conversation.c
===================================================================
--- gnunet/src/conversation/gnunet-conversation.c 2014-01-08 14:14:37 UTC
(rev 31833)
+++ gnunet/src/conversation/gnunet-conversation.c 2014-01-08 14:14:41 UTC
(rev 31834)
@@ -29,15 +29,27 @@
#include "gnunet_gnsrecord_lib.h"
#include "gnunet_conversation_service.h"
#include "gnunet_namestore_service.h"
+#ifdef WINDOWS
+#include "../util/gnunet-helper-w32-console.h"
+#endif
-
/**
* Maximum length allowed for the command line input.
*/
#define MAX_MESSAGE_LENGTH 1024
+#define XSTRINGIFY(x) STRINGIFY(x)
+#define STRINGIFY(x) (#x)
+
+#ifdef WINDOWS
/**
+ * Helper that reads the console for us.
+ */
+struct GNUNET_HELPER_Handle *stdin_hlp;
+#endif
+
+/**
* Possible states of the phone.
*/
enum PhoneState
@@ -997,6 +1009,13 @@
do_stop_task (void *cls,
const struct GNUNET_SCHEDULER_TaskContext *tc)
{
+#ifdef WINDOWS
+ if (NULL != stdin_hlp)
+ {
+ GNUNET_HELPER_stop (stdin_hlp, GNUNET_NO);
+ stdin_hlp = NULL;
+ }
+#endif
if (NULL != call)
{
GNUNET_CONVERSATION_call_stop (call);
@@ -1027,7 +1046,61 @@
phone_state = PS_ERROR;
}
+static void
+handle_command_string (char *message, size_t str_len)
+{
+ size_t i;
+ const char *ptr;
+ if (0 == str_len)
+ return;
+ if (message[str_len - 1] == '\n')
+ message[str_len - 1] = '\0';
+ if (message[str_len - 2] == '\r')
+ message[str_len - 2] = '\0';
+ if (0 == strlen (message))
+ return;
+ i = 0;
+ while ((NULL != commands[i].command) &&
+ (0 != strncasecmp (commands[i].command, message,
+ strlen (commands[i].command))))
+ i++;
+ ptr = &message[strlen (commands[i].command)];
+ while (isspace ((int) *ptr))
+ ptr++;
+ if ('\0' == *ptr)
+ ptr = NULL;
+ commands[i].Action (ptr);
+}
+
+
+#ifdef WINDOWS
+int
+console_reader_chars (void *cls, void *client,
+ const struct GNUNET_MessageHeader *message)
+{
+ char *chars;
+ size_t str_size;
+ switch (ntohs (message->type))
+ {
+ case GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_CHARS:
+ chars = (char *) &message[1];
+ str_size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader);
+ if (chars[str_size - 1] != '\0')
+ return GNUNET_SYSERR;
+ /* FIXME: is it ok that we pass part of a const struct to
+ * this function that may mangle the contents?
+ */
+ handle_command_string (chars, str_size - 1);
+ break;
+ default:
+ GNUNET_break (0);
+ break;
+ }
+ return GNUNET_OK;
+}
+#endif
+
/**
* Task to handle commands from the terminal.
*
@@ -1039,8 +1112,6 @@
const struct GNUNET_SCHEDULER_TaskContext *tc)
{
char message[MAX_MESSAGE_LENGTH + 1];
- const char *ptr;
- size_t i;
handle_cmd_task =
GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
@@ -1050,23 +1121,7 @@
memset (message, 0, MAX_MESSAGE_LENGTH + 1);
if (NULL == fgets (message, MAX_MESSAGE_LENGTH, stdin))
return;
- if (0 == strlen (message))
- return;
- if (message[strlen (message) - 1] == '\n')
- message[strlen (message) - 1] = '\0';
- if (0 == strlen (message))
- return;
- i = 0;
- while ((NULL != commands[i].command) &&
- (0 != strncasecmp (commands[i].command, message,
- strlen (commands[i].command))))
- i++;
- ptr = &message[strlen (commands[i].command)];
- while (isspace ((int) *ptr))
- ptr++;
- if ('\0' == *ptr)
- ptr = NULL;
- commands[i].Action (ptr);
+ handle_command_string (message, strlen (message));
}
@@ -1144,6 +1199,30 @@
id = GNUNET_IDENTITY_connect (cfg,
&identity_cb,
NULL);
+#ifdef WINDOWS
+ if (stdin_fh == NULL)
+ {
+ static char cpid[64];
+ static char *args[] = {"gnunet-helper-w32-console.exe", "chars",
+ XSTRINGIFY (MAX_MESSAGE_LENGTH), cpid, NULL};
+ snprintf (cpid, 64, "%d", GetCurrentProcessId ());
+ stdin_hlp = GNUNET_HELPER_start (
+ GNUNET_NO,
+ "gnunet-helper-w32-console",
+ args,
+ console_reader_chars,
+ NULL,
+ NULL);
+ if (NULL == stdin_hlp)
+ {
+ FPRINTF (stderr,
+ "%s",
+ _("Failed to start gnunet-helper-w32-console\n"));
+ return;
+ }
+ }
+ else
+#endif
handle_cmd_task =
GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_UI,
&handle_command, NULL);
@@ -1171,13 +1250,22 @@
1, &GNUNET_GETOPT_set_uint, &line},
GNUNET_GETOPT_OPTION_END
};
+ int ret;
+#ifndef WINDOWS
int flags;
- int ret;
-
flags = fcntl (0, F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl (0, F_SETFL, flags);
stdin_fh = GNUNET_DISK_get_handle_from_int_fd (0);
+#else
+ if (FILE_TYPE_CHAR == GetFileType ((HANDLE) _get_osfhandle (0)))
+ {
+ stdin_fh = NULL;
+ }
+ else
+ stdin_fh = GNUNET_DISK_get_handle_from_int_fd (0);
+#endif
+
if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
return 2;
ret = GNUNET_PROGRAM_run (argc, argv,
Modified: gnunet/src/util/Makefile.am
===================================================================
--- gnunet/src/util/Makefile.am 2014-01-08 14:14:37 UTC (rev 31833)
+++ gnunet/src/util/Makefile.am 2014-01-08 14:14:41 UTC (rev 31834)
@@ -25,6 +25,7 @@
-lcomdlg32 -lgdi32 -liphlpapi
WINLIB = libgnunetutilwin.la
W32CAT = w32cat
+W32CONSOLEHELPER = gnunet-helper-w32-console
endif
if !MINGW
@@ -38,6 +39,14 @@
w32cat_SOURCES = w32cat.c
+gnunet_helper_w32_console_SOURCES = \
+ gnunet-helper-w32-console.c \
+ gnunet-helper-w32-console.h
+gnunet_helper_w32_console_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la
+gnunet_helper_w32_console_DEPENDENCIES = \
+ libgnunetutil.la
+
noinst_PROGRAMS = \
gnunet-config-diff \
$(W32CAT) \
@@ -126,7 +135,8 @@
libexec_PROGRAMS = \
- gnunet-service-resolver
+ gnunet-service-resolver \
+ $(W32CONSOLEHELPER)
bin_SCRIPTS =\
gnunet-qr
Added: gnunet/src/util/gnunet-helper-w32-console.c
===================================================================
--- gnunet/src/util/gnunet-helper-w32-console.c (rev 0)
+++ gnunet/src/util/gnunet-helper-w32-console.c 2014-01-08 14:14:41 UTC (rev
31834)
@@ -0,0 +1,318 @@
+/*
+ This file is part of GNUnet.
+ (C) 2014 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file src/util/gnunet-helper-w32-console.c
+ * @brief Does blocking reads from the console, writes the results
+ * into stdout, turning blocking console I/O into non-blocking
+ * pipe I/O. For W32 only.
+ * @author LRN
+ */
+#include "platform.h"
+#include "gnunet_crypto_lib.h"
+#include "gnunet_common.h"
+#include "gnunet-helper-w32-console.h"
+
+static unsigned long buffer_size;
+
+static int chars;
+
+static HANDLE parent_handle;
+
+/**
+ * Write @a size bytes from @a buf into @a output.
+ *
+ * @param output the descriptor to write into
+ * @param buf buffer with data to write
+ * @param size number of bytes to write
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+static int
+write_all (int output,
+ const void *buf,
+ size_t size)
+{
+ const char *cbuf = buf;
+ size_t total;
+ ssize_t wr;
+
+ total = 0;
+ do
+ {
+ wr = write (output,
+ &cbuf[total],
+ size - total);
+ if (wr > 0)
+ total += wr;
+ } while ( (wr > 0) && (total < size) );
+ if (wr <= 0)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Failed to write to stdout: %s\n",
+ strerror (errno));
+ return (total == size) ? GNUNET_OK : GNUNET_SYSERR;
+}
+
+
+/**
+ * Write message to the master process.
+ *
+ * @param output the descriptor to write into
+ * @param message_type message type to use
+ * @param data data to append, NULL for none
+ * @param data_length number of bytes in @a data
+ * @return #GNUNET_SYSERR to stop scanning (the pipe was broken somehow)
+ */
+static int
+write_message (int output,
+ uint16_t message_type,
+ const char *data,
+ size_t data_length)
+{
+ struct GNUNET_MessageHeader hdr;
+
+#if 0
+ fprintf (stderr,
+ "Helper sends %u-byte message of type %u\n",
+ (unsigned int) (sizeof (struct GNUNET_MessageHeader) + data_length),
+ (unsigned int) message_type);
+#endif
+ hdr.type = htons (message_type);
+ hdr.size = htons (sizeof (struct GNUNET_MessageHeader) + data_length);
+ if (GNUNET_OK != write_all (output, &hdr, sizeof (hdr)))
+ return GNUNET_SYSERR;
+ if (GNUNET_OK != write_all (output, data, data_length))
+ return GNUNET_SYSERR;
+ return GNUNET_OK;
+}
+
+
+/**
+ * Main function of the helper process. Reads input events from console,
+ * writes messages, into stdout.
+ *
+ * @param console a handle to a console to read from
+ * @param output_stream a stream to write messages to
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+static int
+read_events (HANDLE console, int output_stream)
+{
+ DWORD rr;
+ BOOL b;
+ INPUT_RECORD *buf;
+ DWORD i;
+ int result;
+
+ result = GNUNET_SYSERR;
+ buf = malloc (sizeof (INPUT_RECORD) * buffer_size);
+ if (NULL == buf)
+ return result;
+ b = TRUE;
+ rr = 1;
+ while (TRUE == b && 0 < rr)
+ {
+ rr = 0;
+ b = ReadConsoleInput (console, buf, buffer_size, &rr);
+ if (FALSE == b && ERROR_SUCCESS != GetLastError ())
+ break;
+ for (i = 0; i < rr; i++)
+ {
+ int r;
+ r = write_message (output_stream,
+ GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_INPUT,
+ (const char *) &buf[i],
+ sizeof (INPUT_RECORD));
+ if (GNUNET_OK != r)
+ break;
+ }
+ if (rr + 1 != i)
+ break;
+ }
+ return result;
+}
+
+
+/**
+ * Main function of the helper process. Reads chars from console,
+ * writes messages, into stdout.
+ *
+ * @param console a handle to a console to read from
+ * @param output_stream a stream to write messages to
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+static int
+read_chars (HANDLE console, int output_stream)
+{
+ DWORD rr;
+ BOOL b;
+ wchar_t *buf;
+ char *small_ubuf;
+ char *large_ubuf;
+ char *ubuf;
+ int conv;
+ int r;
+ int result;
+
+ result = GNUNET_SYSERR;
+ buf = malloc (sizeof (wchar_t) * buffer_size);
+ if (NULL == buf)
+ return result;
+ small_ubuf = malloc (sizeof (char) * buffer_size * 2);
+ if (NULL == small_ubuf)
+ {
+ free (buf);
+ return result;
+ }
+ b = TRUE;
+ rr = 1;
+ while (TRUE == b)
+ {
+ large_ubuf = NULL;
+ rr = 0;
+ b = ReadConsoleW (console, buf, buffer_size, &rr, NULL);
+ if (FALSE == b && ERROR_SUCCESS != GetLastError ())
+ break;
+ if (0 == rr)
+ continue;
+ /* Caveat: if the UTF-16-encoded string is longer than BUFFER_SIZE,
+ * there's a possibility that we will read up to a word that constitutes
+ * a part of a multi-byte UTF-16 codepoint. Converting that to UTF-8
+ * will either drop invalid word (flags == 0) or bail out because of it
+ * (flags == WC_ERR_INVALID_CHARS).
+ */
+ conv = WideCharToMultiByte (CP_UTF8, 0, buf, rr, small_ubuf, 0, NULL,
FALSE);
+ if (0 == conv || 0xFFFD == conv)
+ continue;
+ if (conv <= buffer_size * 2 - 1)
+ {
+ memset (small_ubuf, 0, buffer_size * 2);
+ conv = WideCharToMultiByte (CP_UTF8, 0, buf, rr, small_ubuf, buffer_size
* 2 - 1, NULL, FALSE);
+ if (0 == conv || 0xFFFD == conv)
+ continue;
+ ubuf = small_ubuf;
+ }
+ else
+ {
+ large_ubuf = malloc (conv + 1);
+ if (NULL == large_ubuf)
+ continue;
+ memset (large_ubuf, 0, conv + 1);
+ conv = WideCharToMultiByte (CP_UTF8, 0, buf, rr, large_ubuf, conv, NULL,
FALSE);
+ if (0 == conv || 0xFFFD == conv)
+ {
+ free (large_ubuf);
+ large_ubuf = NULL;
+ continue;
+ }
+ ubuf = large_ubuf;
+ }
+ r = write_message (output_stream,
+ GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_CHARS,
+ ubuf,
+ conv + 1);
+ if (large_ubuf)
+ free (large_ubuf);
+ if (GNUNET_OK != r)
+ break;
+ }
+ free (small_ubuf);
+ free (buf);
+ return result;
+}
+
+
+DWORD WINAPI
+watch_parent (LPVOID param)
+{
+ WaitForSingleObject (parent_handle, INFINITE);
+ ExitProcess (1);
+ return 0;
+}
+
+/**
+ * Main function of the helper process to extract meta data.
+ *
+ * @param argc should be 3
+ * @param argv [0] our binary name
+ * [1] name of the file or directory to process
+ * [2] "-" to disable extraction, NULL for defaults,
+ * otherwise custom plugins to load from LE
+ * @return 0 on success
+ */
+int
+main (int argc,
+ char *const *argv)
+{
+ HANDLE os_stdin;
+ DWORD parent_pid;
+ /* We're using stdout to communicate binary data back to the parent; use
+ * binary mode.
+ */
+ _setmode (1, _O_BINARY);
+
+ if (argc != 4)
+ {
+ fprintf (stderr,
+ "Usage: gnunet-helper-w32-console <chars|events> <buffer size> <parent
pid>\n");
+ return 2;
+ }
+
+ if (0 == strcmp (argv[1], "chars"))
+ chars = GNUNET_YES;
+ else if (0 == strcmp (argv[1], "events"))
+ chars = GNUNET_NO;
+ else
+ return 3;
+
+ buffer_size = strtoul (argv[2], NULL, 10);
+ if (buffer_size <= 0)
+ return 4;
+
+ parent_pid = (DWORD) strtoul (argv[3], NULL, 10);
+ if (parent_pid == 0)
+ return 5;
+ parent_handle = OpenProcess (SYNCHRONIZE, FALSE, parent_pid);
+ if (NULL == parent_handle)
+ return 6;
+
+ CreateThread (NULL, 0, watch_parent, NULL, 0, NULL);
+
+ if (0 == AttachConsole (ATTACH_PARENT_PROCESS))
+ {
+ if (ERROR_ACCESS_DENIED != GetLastError ())
+ return 5;
+ }
+
+ /* Helper API overrides stdin, so we just attach to the console that we
+ * inherited. If we did.
+ */
+ os_stdin = CreateFile ("CONIN$", GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
+ if (INVALID_HANDLE_VALUE == os_stdin)
+ return 1;
+
+ if (GNUNET_NO == chars)
+ return read_events (os_stdin, 1);
+ else
+ return read_chars (os_stdin, 1);
+
+}
+
+/* end of gnunet-helper-w32-console.c */
Property changes on: gnunet/src/util/gnunet-helper-w32-console.c
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: gnunet/src/util/gnunet-helper-w32-console.h
===================================================================
--- gnunet/src/util/gnunet-helper-w32-console.h (rev 0)
+++ gnunet/src/util/gnunet-helper-w32-console.h 2014-01-08 14:14:41 UTC (rev
31834)
@@ -0,0 +1,72 @@
+/*
+ This file is part of GNUnet.
+ (C) 2014 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @author LRN
+ * @file src/util/gnunet-helper-w32-console.h
+ */
+#ifndef GNUNET_HELPER_W32_CONSOLE_H
+#define GNUNET_HELPER_W32_CONSOLE_H
+
+#include "platform.h"
+#include "gnunet_crypto_lib.h"
+#include "gnunet_common.h"
+
+/**
+ * Input event from the console
+ */
+#define GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_INPUT 60000
+
+/**
+ * Chars from the console
+ */
+#define GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_CHARS 60001
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * This is just a dump of the INPUT_RECORD structure.
+ */
+struct GNUNET_W32_CONSOLE_input
+{
+ /**
+ * Type: GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_INPUT
+ */
+ struct GNUNET_MessageHeader header;
+
+ INPUT_RECORD input_record GNUNET_PACKED;
+};
+
+/**
+ * A header, followed by UTF8-encoded, 0-terminated string
+ */
+struct GNUNET_W32_CONSOLE_chars
+{
+ /**
+ * Type: GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_CHARS
+ */
+ struct GNUNET_MessageHeader header;
+
+ /* followed by a string */
+};
+
+GNUNET_NETWORK_STRUCT_END
+
+#endif
Property changes on: gnunet/src/util/gnunet-helper-w32-console.h
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r31834 - in gnunet/src: conversation util,
gnunet <=