Index: src/arm/gnunet-service-arm_interceptor.c =================================================================== --- src/arm/gnunet-service-arm_interceptor.c (revision 13603) +++ src/arm/gnunet-service-arm_interceptor.c (working copy) @@ -187,9 +187,15 @@ * Have we ever successfully written data to the service? */ int first_write_done; + + + /** + * Service connection attempts + */ + struct ServiceListeningInfo *service_connect_ipv4; + struct ServiceListeningInfo *service_connect_ipv6; }; - /** * Array with the names of the services started by default. */ @@ -694,6 +700,10 @@ &forwardToService, fc); } +static void fc_acceptConnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc, int is_ipv4, int is_ipv6); +static void fc_acceptConnection_ipv4 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); +static void fc_acceptConnection_ipv6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); +static int service_try_to_connect (struct sockaddr *addr, socklen_t addrlen, struct ForwardedConnection *fc); /** * @@ -704,103 +714,252 @@ { struct ForwardedConnection *fc = cls; struct GNUNET_TIME_Relative rem; + int fail = 0; + int failures = 0; + int is_zero = 0, is_ipv6 = 0, is_ipv4 = 0; + struct sockaddr_in *target_ipv4; + struct sockaddr_in6 *target_ipv6; + int free_ipv4 = 1, free_ipv6 = 1; + char listen_address[128]; + uint16_t listening_port; + fc->start_task = GNUNET_SCHEDULER_NO_TASK; if ( (NULL != tc) && (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Unable to forward to service `%s': shutdown\n"), - fc->listen_info->serviceName); - closeClientAndServiceSockets (fc, REASON_ERROR); - return; - } + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Unable to forward to service `%s': shutdown\n"), + fc->listen_info->serviceName); + closeClientAndServiceSockets (fc, REASON_ERROR); + return; + } rem = GNUNET_TIME_absolute_get_remaining (fc->timeout); if (rem.rel_value == 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Unable to forward to service `%s': timeout before connect\n"), + fc->listen_info->serviceName); + closeClientAndServiceSockets (fc, REASON_ERROR); + return; + } + target_ipv4 = GNUNET_malloc (sizeof (struct sockaddr_in)); + target_ipv6 = GNUNET_malloc (sizeof (struct sockaddr_in6)); + + switch (fc->listen_info->service_addr->sa_family) + { + case AF_INET: + inet_ntop (fc->listen_info->service_addr->sa_family, (const void *) &((struct sockaddr_in *) fc->listen_info->service_addr)->sin_addr, listen_address, INET_ADDRSTRLEN); + if (strncmp (listen_address, "0.0.0.0:", 8) == 0 || strncmp (listen_address, "0.0.0.0", 7) == 0) + is_zero = 1; + is_ipv4 = 1; + listening_port = ((struct sockaddr_in *)fc->listen_info->service_addr)->sin_port; + break; + case AF_INET6: + inet_ntop (fc->listen_info->service_addr->sa_family, (const void *) &((struct sockaddr_in6 *) fc->listen_info->service_addr)->sin6_addr, listen_address, INET6_ADDRSTRLEN); + if (strncmp (listen_address, "[::]:", 5) == 0 || strncmp (listen_address, "::", 2) == 0) + is_zero = 1; + is_ipv6 = 1; + listening_port = ((struct sockaddr_in6 *)fc->listen_info->service_addr)->sin6_port; + break; + default: + break; + } + + fc->service_connect_ipv4 = NULL; + fc->service_connect_ipv6 = NULL; + if (is_zero) + { + /* connect to [::1] and 127.0.0.1 instead of [::] and 0.0.0.0 */ + inet_pton (AF_INET, "127.0.0.1", &target_ipv4->sin_addr); + target_ipv4->sin_family = AF_INET; + target_ipv4->sin_port = listening_port; + is_ipv4 = 1; + free_ipv4 = 0; + + inet_pton (AF_INET6, "0:0:0:0:0:0:0:1", &target_ipv6->sin6_addr); + target_ipv6->sin6_family = AF_INET6; + target_ipv6->sin6_port = listening_port; + is_ipv6 = 1; + free_ipv6 = 0; + } + else + { + if (is_ipv4) + memcpy (target_ipv4, fc->listen_info->service_addr, sizeof (struct sockaddr_in)); + else if (is_ipv6) + memcpy (target_ipv6, fc->listen_info->service_addr, sizeof (struct sockaddr_in6)); + } + + if (is_ipv4) + failures += free_ipv4 = service_try_to_connect ((struct sockaddr *) target_ipv4, sizeof (struct sockaddr_in), fc); + if (is_ipv6) + failures += free_ipv6 = service_try_to_connect ((struct sockaddr *) target_ipv6, sizeof (struct sockaddr_in6), fc); + + if (is_ipv4 + is_ipv6 <= failures) + fail = 1; + + if (free_ipv4) + GNUNET_free (target_ipv4); + if (free_ipv6) + GNUNET_free (target_ipv6); + + if (fail) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _ ("Unable to start service `%s': %s\n"), + fc->listen_info->serviceName, + STRERROR (errno)); + closeClientAndServiceSockets (fc, REASON_ERROR); + return; + } +} + +static void +fc_acceptConnection_ipv4 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + fc_acceptConnection (cls, tc, 1, 0); +} + +static void +fc_acceptConnection_ipv6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + fc_acceptConnection (cls, tc, 0, 1); +} + +static void +fc_acceptConnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc, int is_ipv4, int is_ipv6) +{ + struct ForwardedConnection *fc = cls; + struct ServiceListeningInfo *sli; + + if (is_ipv4) + sli = fc->service_connect_ipv4; + else if (is_ipv6) + sli = fc->service_connect_ipv6; + else + GNUNET_break (0); + + if ((tc->reason & (GNUNET_SCHEDULER_REASON_SHUTDOWN | GNUNET_SCHEDULER_REASON_TIMEOUT | GNUNET_SCHEDULER_REASON_PREREQ_DONE)) || ((tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY) && fc->armServiceSocket)) + { + GNUNET_NETWORK_socket_close (sli->listeningSocket); + if (is_ipv4) + fc->service_connect_ipv4 = NULL; + else if (is_ipv6) + fc->service_connect_ipv6 = NULL; + } + else if (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY) + { +#if DEBUG_SERVICE_MANAGER + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Connected to service, now starting forwarding\n"); +#endif + fc->armServiceSocket = sli->listeningSocket; + if ((is_ipv4 && fc->service_connect_ipv6 != NULL)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Unable to forward to service `%s': timeout before connect\n"), - fc->listen_info->serviceName); - closeClientAndServiceSockets (fc, REASON_ERROR); - return; + GNUNET_SCHEDULER_cancel (fc->service_connect_ipv6->acceptTask); + fc->service_connect_ipv6->acceptTask = GNUNET_SCHEDULER_add_now (fc_acceptConnection_ipv6, fc); } - fc->armServiceSocket = - GNUNET_NETWORK_socket_create (fc->listen_info->service_addr->sa_family, - SOCK_STREAM, 0); - if (NULL == fc->armServiceSocket) + else if (is_ipv6 && fc->service_connect_ipv4 != NULL) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ ("Unable to start service `%s': %s\n"), - fc->listen_info->serviceName, - STRERROR (errno)); - closeClientAndServiceSockets (fc, REASON_ERROR); - return; + GNUNET_SCHEDULER_cancel (fc->service_connect_ipv4->acceptTask); + fc->service_connect_ipv4->acceptTask = GNUNET_SCHEDULER_add_now (fc_acceptConnection_ipv4, fc); } - if ( (GNUNET_SYSERR == - GNUNET_NETWORK_socket_connect (fc->armServiceSocket, - fc->listen_info->service_addr, - fc->listen_info->service_addr_len)) && - (errno != EINPROGRESS) ) + GNUNET_free (fc->listen_info->service_addr); + fc->listen_info->service_addr = sli->service_addr; + fc->listen_info->service_addr_len = sli->service_addr_len; + /*fc->listen_info->listeningSocket is it closed already?*/ + if (fc->client_to_service_task == GNUNET_SCHEDULER_NO_TASK) { - GNUNET_break (GNUNET_OK == - GNUNET_NETWORK_socket_close (fc->armServiceSocket)); - fc->armServiceSocket = NULL; - fc->back_off = GNUNET_TIME_relative_multiply (fc->back_off, 2); - #if DEBUG_SERVICE_MANAGER - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Failed to connected to service `%s' at `%s', will try again in %llu ms\n", - fc->listen_info->serviceName, - GNUNET_a2s (fc->listen_info->service_addr, - fc->listen_info->service_addr_len), - (unsigned long long) GNUNET_TIME_relative_min (fc->back_off, - rem).rel_value); -#endif - GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == fc->start_task); - fc->start_task - = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_min (fc->back_off, - rem), - &start_forwarding, - fc); - return; - } -#if DEBUG_SERVICE_MANAGER - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connected to service, now starting forwarding\n"); -#endif - if (fc->client_to_service_task == GNUNET_SCHEDULER_NO_TASK) - { if (fc->client_to_service_bufferDataLength == 0) - fc->client_to_service_task = - GNUNET_SCHEDULER_add_read_net ( + fc->client_to_service_task = + GNUNET_SCHEDULER_add_read_net ( GNUNET_TIME_UNIT_FOREVER_REL, fc->armClientSocket, &receiveFromClient, fc); else - fc->client_to_service_task = - GNUNET_SCHEDULER_add_write_net ( + fc->client_to_service_task = + GNUNET_SCHEDULER_add_write_net ( GNUNET_TIME_UNIT_FOREVER_REL, fc->armServiceSocket, &forwardToService, fc); } - if (fc->service_to_client_task == GNUNET_SCHEDULER_NO_TASK) + if (fc->service_to_client_task == GNUNET_SCHEDULER_NO_TASK) { if (fc->service_to_client_bufferDataLength == 0) - fc->service_to_client_task = - GNUNET_SCHEDULER_add_read_net ( + fc->service_to_client_task = + GNUNET_SCHEDULER_add_read_net ( GNUNET_TIME_UNIT_FOREVER_REL, fc->armServiceSocket, &receiveFromService, fc); else - fc->service_to_client_task = - GNUNET_SCHEDULER_add_write_net ( + fc->service_to_client_task = + GNUNET_SCHEDULER_add_write_net ( GNUNET_TIME_UNIT_FOREVER_REL, fc->armClientSocket, &forwardToClient, fc); } + } + else + { + GNUNET_break (0); + } + GNUNET_free (sli); } +static int +service_try_to_connect (struct sockaddr *addr, socklen_t addrlen, struct ForwardedConnection *fc) +{ + struct GNUNET_NETWORK_Handle *sock; + struct ServiceListeningInfo *serviceListeningInfo; + sock = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0); + if (sock == NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to create a socket\n"); + return 1; + } + + if ( (GNUNET_SYSERR == GNUNET_NETWORK_socket_connect (sock, addr, addrlen)) && + (errno != EINPROGRESS) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to connect\n"); + GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); + return 1; + } + serviceListeningInfo = GNUNET_malloc (sizeof (struct ServiceListeningInfo)); + serviceListeningInfo->serviceName = NULL; + serviceListeningInfo->service_addr = addr; + serviceListeningInfo->service_addr_len = addrlen; + serviceListeningInfo->listeningSocket = sock; + + switch (addrlen) + { + case sizeof (struct sockaddr_in): + fc->service_connect_ipv4 = serviceListeningInfo; + serviceListeningInfo->acceptTask = + GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, + serviceListeningInfo->listeningSocket, + &fc_acceptConnection_ipv4, fc); + break; + case sizeof (struct sockaddr_in6): + fc->service_connect_ipv6 = serviceListeningInfo; + serviceListeningInfo->acceptTask = + GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, + serviceListeningInfo->listeningSocket, + &fc_acceptConnection_ipv6, fc); + break; + default: + GNUNET_break (0); + return 1; + break; + } + return 0; +} + + + /** * */ Index: src/include/gnunet_os_lib.h =================================================================== --- src/include/gnunet_os_lib.h (revision 13603) +++ src/include/gnunet_os_lib.h (working copy) @@ -273,6 +273,18 @@ */ int GNUNET_OS_process_wait (struct GNUNET_OS_Process *proc); +/** + * Read env variable and set up the read end of the control + * pipe that parent uses to send signals to this process. + * + * Only does something on Windows + * + * @param cls user-specified parameter (NULL) + * @param tc task context + */ +void GNUNET_OS_install_parent_control_handler (void *cls, + const struct + GNUNET_SCHEDULER_TaskContext * tc); #if 0 /* keep Emacsens' auto-indent happy */ { Index: src/transport/plugin_transport_http.c =================================================================== --- src/transport/plugin_transport_http.c (revision 13603) +++ src/transport/plugin_transport_http.c (working copy) @@ -1589,7 +1589,7 @@ if (delay.rel_value > 0) { #if DEBUG_HTTP - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Connection %X: Inbound quota management: delay next read for %llu ms \n", ps, delay.abs_value); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Connection %X: Inbound quota management: delay next read for %llu ms \n", ps, delay.rel_value); #endif pc->reset_task = GNUNET_SCHEDULER_add_delayed (delay, &reset_inbound_quota_delay, pc); } Index: src/fragmentation/test_frag_ji.c =================================================================== --- src/fragmentation/test_frag_ji.c (revision 13603) +++ src/fragmentation/test_frag_ji.c (working copy) @@ -1,60 +1,60 @@ -#include "platform.h" -#include "gnunet_protocols.h" -#include "gnunet_fragmentation_lib.h" - -struct combine{ - struct GNUNET_FRAGMENT_Context* ctx; - struct GNUNET_PeerIdentity* sender; -}; - -void message_proc1(void *cls, const struct GNUNET_MessageHeader * msg){ - fprintf(stderr, "enter into message_proc1\n"); - - struct GNUNET_MessageHeader * originalMsg = (struct GNUNET_MessageHeader *)cls; - - if(ntohs(originalMsg->size) != ntohs(msg->size)){ - fprintf(stderr, "the received message has the different size with the sent one!\n"); - } - if(ntohs(originalMsg->type) != ntohs(msg->type)){ - fprintf(stderr, "the received message has the different type with the sent one!\n"); - } - if(memcmp(msg, originalMsg, originalMsg->size)){ - fprintf(stderr, "the received message is not the sent one!\n"); - } - else{ - fprintf(stdout, "You got the right message!\n"); - } - -} - -void message_proc2(void *cls, const struct GNUNET_MessageHeader * msg){ - printf("enter into message_proc2\n"); - struct combine * com2 = (struct combine* )cls; - GNUNET_FRAGMENT_process(com2->ctx, com2->sender, msg); - -} - -int -main(int argc, char * argv[]){ +#include "platform.h" +#include "gnunet_protocols.h" +#include "gnunet_fragmentation_lib.h" + +struct combine{ + struct GNUNET_FRAGMENT_Context* ctx; + struct GNUNET_PeerIdentity* sender; +}; + +void message_proc1(void *cls, const struct GNUNET_MessageHeader * msg){ + fprintf(stderr, "enter into message_proc1\n"); + + struct GNUNET_MessageHeader * originalMsg = (struct GNUNET_MessageHeader *)cls; + + if(ntohs(originalMsg->size) != ntohs(msg->size)){ + fprintf(stderr, "the received message has the different size with the sent one!\n"); + } + if(ntohs(originalMsg->type) != ntohs(msg->type)){ + fprintf(stderr, "the received message has the different type with the sent one!\n"); + } + if(memcmp(msg, originalMsg, originalMsg->size)){ + fprintf(stderr, "the received message is not the sent one!\n"); + } + else{ + fprintf(stdout, "You got the right message!\n"); + } + +} + +void message_proc2(void *cls, const struct GNUNET_MessageHeader * msg){ + printf("enter into message_proc2\n"); + struct combine * com2 = (struct combine* )cls; + GNUNET_FRAGMENT_process(com2->ctx, com2->sender, msg); + +} + +int +main(int argc, char * argv[]){ - uint32_t mtu = 512; - struct GNUNET_FRAGMENT_Context * ctx; - struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *)GNUNET_malloc(sizeof(struct GNUNET_MessageHeader)+2*mtu); - ctx = GNUNET_FRAGMENT_context_create(NULL, message_proc1, msg); - msg->size = htons(sizeof(struct GNUNET_MessageHeader)+4*mtu); - msg->type = htons(GNUNET_MESSAGE_TYPE_HELLO); - struct GNUNET_PeerIdentity *sender; - sender = (struct GNUNET_PeerIdentity *)GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity)); - - memset(sender, 9, sizeof(struct GNUNET_PeerIdentity)); - - memset(&msg[1], 5, 2*mtu); - - struct combine *com; - com = (struct combine *)GNUNET_malloc(sizeof(struct combine)); - com->ctx = ctx; - com->sender = sender; - GNUNET_FRAGMENT_fragment(msg, mtu, message_proc2, com); - GNUNET_free(msg); - return 0; -} + uint32_t mtu = 512; + struct GNUNET_FRAGMENT_Context * ctx; + struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *)GNUNET_malloc(sizeof(struct GNUNET_MessageHeader)+2*mtu); + ctx = GNUNET_FRAGMENT_context_create(NULL, message_proc1, msg); + msg->size = htons(sizeof(struct GNUNET_MessageHeader)+4*mtu); + msg->type = htons(GNUNET_MESSAGE_TYPE_HELLO); + struct GNUNET_PeerIdentity *sender; + sender = (struct GNUNET_PeerIdentity *)GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity)); + + memset(sender, 9, sizeof(struct GNUNET_PeerIdentity)); + + memset(&msg[1], 5, 2*mtu); + + struct combine *com; + com = (struct combine *)GNUNET_malloc(sizeof(struct combine)); + com->ctx = ctx; + com->sender = sender; + GNUNET_FRAGMENT_fragment(msg, mtu, message_proc2, com); + GNUNET_free(msg); + return 0; +} Index: src/fragmentation/test_fragmentation_enhanced.c =================================================================== --- src/fragmentation/test_fragmentation_enhanced.c (revision 13603) +++ src/fragmentation/test_fragmentation_enhanced.c (working copy) @@ -1,89 +1,89 @@ -/* - This file is part of GNUnet. - (C) 2009 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 fragmentation/test_fragmentation_enhanced.c - * @brief testcase for the fragmentation.c - * @author Ji Lu - */ - -#include "platform.h" -#include "gnunet_protocols.h" -#include "gnunet_fragmentation_lib.h" - -struct combine{ - struct GNUNET_FRAGMENT_Context* ctx; - struct GNUNET_PeerIdentity* sender; -}; - -void message_proc1(void *cls, const struct GNUNET_MessageHeader * msg){ - - fprintf(stderr, "enter into message_proc1\n"); - - struct GNUNET_MessageHeader * originalMsg = (struct GNUNET_MessageHeader *)cls; - - if(ntohs(originalMsg->size) != ntohs(msg->size)){ - fprintf(stderr, "the received message has the different size with the sent one!\n"); - } - if(ntohs(originalMsg->type) != ntohs(msg->type)){ - fprintf(stderr, "the received message has the different type with the sent one!\n"); - } - if(memcmp(msg, originalMsg, originalMsg->size)){ - fprintf(stderr, "the received message is not the sent one!\n"); - } - else{ - fprintf(stdout, "You got the right message!\n"); - } - -} - -void message_proc2(void *cls, const struct GNUNET_MessageHeader * msg){ - - printf("enter into message_proc2\n"); - - struct combine * com2 = (struct combine* )cls; - GNUNET_FRAGMENT_process(com2->ctx, com2->sender, msg); - -} - -int -main(int argc, char * argv[]){ +/* + This file is part of GNUnet. + (C) 2009 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 fragmentation/test_fragmentation_enhanced.c + * @brief testcase for the fragmentation.c + * @author Ji Lu + */ + +#include "platform.h" +#include "gnunet_protocols.h" +#include "gnunet_fragmentation_lib.h" + +struct combine{ + struct GNUNET_FRAGMENT_Context* ctx; + struct GNUNET_PeerIdentity* sender; +}; + +void message_proc1(void *cls, const struct GNUNET_MessageHeader * msg){ + + fprintf(stderr, "enter into message_proc1\n"); + + struct GNUNET_MessageHeader * originalMsg = (struct GNUNET_MessageHeader *)cls; + + if(ntohs(originalMsg->size) != ntohs(msg->size)){ + fprintf(stderr, "the received message has the different size with the sent one!\n"); + } + if(ntohs(originalMsg->type) != ntohs(msg->type)){ + fprintf(stderr, "the received message has the different type with the sent one!\n"); + } + if(memcmp(msg, originalMsg, originalMsg->size)){ + fprintf(stderr, "the received message is not the sent one!\n"); + } + else{ + fprintf(stdout, "You got the right message!\n"); + } + +} + +void message_proc2(void *cls, const struct GNUNET_MessageHeader * msg){ + + printf("enter into message_proc2\n"); + + struct combine * com2 = (struct combine* )cls; + GNUNET_FRAGMENT_process(com2->ctx, com2->sender, msg); + +} + +int +main(int argc, char * argv[]){ - uint32_t mtu = 512; - struct GNUNET_FRAGMENT_Context * ctx; - struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *)GNUNET_malloc(sizeof(struct GNUNET_MessageHeader)+2*mtu); - ctx = GNUNET_FRAGMENT_context_create(NULL, message_proc1, msg); - msg->size = htons(sizeof(struct GNUNET_MessageHeader)+4*mtu); - msg->type = htons(GNUNET_MESSAGE_TYPE_HELLO); - struct GNUNET_PeerIdentity *sender; - sender = (struct GNUNET_PeerIdentity *)GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity)); - - memset(sender, 9, sizeof(struct GNUNET_PeerIdentity)); - - memset(&msg[1], 5, 2*mtu); - - struct combine *com; - com = (struct combine *)GNUNET_malloc(sizeof(struct combine)); - com->ctx = ctx; - com->sender = sender; - GNUNET_FRAGMENT_fragment(msg, mtu, message_proc2, com); - GNUNET_free(msg); - return 0; -} + uint32_t mtu = 512; + struct GNUNET_FRAGMENT_Context * ctx; + struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *)GNUNET_malloc(sizeof(struct GNUNET_MessageHeader)+2*mtu); + ctx = GNUNET_FRAGMENT_context_create(NULL, message_proc1, msg); + msg->size = htons(sizeof(struct GNUNET_MessageHeader)+4*mtu); + msg->type = htons(GNUNET_MESSAGE_TYPE_HELLO); + struct GNUNET_PeerIdentity *sender; + sender = (struct GNUNET_PeerIdentity *)GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity)); + + memset(sender, 9, sizeof(struct GNUNET_PeerIdentity)); + + memset(&msg[1], 5, 2*mtu); + + struct combine *com; + com = (struct combine *)GNUNET_malloc(sizeof(struct combine)); + com->ctx = ctx; + com->sender = sender; + GNUNET_FRAGMENT_fragment(msg, mtu, message_proc2, com); + GNUNET_free(msg); + return 0; +} Index: src/hostlist/hostlist-client.c =================================================================== --- src/hostlist/hostlist-client.c (revision 13603) +++ src/hostlist/hostlist-client.c (working copy) @@ -1421,6 +1421,7 @@ "HOSTLISTFILE", "HOSTLIST"); return; } + GNUNET_DISK_directory_create_for_file (filename); wh = GNUNET_BIO_write_open (filename); if ( NULL == wh) { Index: src/util/scheduler.c =================================================================== --- src/util/scheduler.c (revision 13603) +++ src/util/scheduler.c (working copy) @@ -744,6 +744,7 @@ shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, &sighandler_shutdown); #endif current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; + GNUNET_SCHEDULER_add_continuation (GNUNET_OS_install_parent_control_handler, NULL, GNUNET_SCHEDULER_REASON_STARTUP); GNUNET_SCHEDULER_add_continuation (task, task_cls, GNUNET_SCHEDULER_REASON_STARTUP); @@ -1351,8 +1352,7 @@ GNUNET_assert (rfd != NULL); rs = GNUNET_NETWORK_fdset_create (); GNUNET_NETWORK_fdset_handle_set (rs, rfd); - ret = GNUNET_SCHEDULER_add_select (sched, - GNUNET_SCHEDULER_PRIORITY_KEEP, + ret = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_KEEP, GNUNET_SCHEDULER_NO_TASK, delay, rs, NULL, task, task_cls); GNUNET_NETWORK_fdset_destroy (rs); @@ -1400,8 +1400,7 @@ GNUNET_assert (wfd != NULL); ws = GNUNET_NETWORK_fdset_create (); GNUNET_NETWORK_fdset_handle_set (ws, wfd); - ret = GNUNET_SCHEDULER_add_select (sched, - GNUNET_SCHEDULER_PRIORITY_KEEP, + ret = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_KEEP, GNUNET_SCHEDULER_NO_TASK, delay, NULL, ws, task, task_cls); GNUNET_NETWORK_fdset_destroy (ws); Index: src/util/os_priority.c =================================================================== --- src/util/os_priority.c (revision 13557) +++ src/util/os_priority.c (working copy) @@ -29,28 +29,95 @@ #include "gnunet_os_lib.h" #include "disk.h" +#define GNUNET_OS_NT_CONTROL_PIPE "GNUNET_OS_NT_CONTROL_PIPE" + struct GNUNET_OS_Process { pid_t pid; #if WINDOWS HANDLE handle; + struct GNUNET_DISK_PipeHandle *control_pipe; #endif }; static struct GNUNET_OS_Process current_process; - #if WINDOWS -void -GNUNET_OS_process_set_handle(struct GNUNET_OS_Process *proc, HANDLE handle) +void GNUNET_OS_parent_control_handler (void *cls, + const struct + GNUNET_SCHEDULER_TaskContext * tc) { - if (proc->handle != NULL) - CloseHandle (proc->handle); - proc->handle = handle; + struct GNUNET_DISK_PipeHandle *control_pipe = (struct GNUNET_DISK_PipeHandle *) cls; + unsigned char code; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_OS_parent_control_handler is invoked because of %d\n", tc->reason); + + if (tc->reason & (GNUNET_SCHEDULER_REASON_SHUTDOWN | GNUNET_SCHEDULER_REASON_TIMEOUT | GNUNET_SCHEDULER_REASON_PREREQ_DONE)) + { + GNUNET_DISK_pipe_close (control_pipe); + } + else + { + if (GNUNET_DISK_file_read (GNUNET_DISK_pipe_handle (control_pipe, GNUNET_DISK_PIPE_END_READ), &code, sizeof (char)) != sizeof (char)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_DISK_file_read have failed, errno = %d. Closing the control pipe.\n", errno); + GNUNET_DISK_pipe_close (control_pipe); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got control code %d\n", code); + switch (code) + { + case 0: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Raising SIGTERM\n"); + raise (SIGTERM); + break; + case 1: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Raising SIGKILL\n"); + raise (SIGKILL); + break; + case 255: + /* read more bytes - a possibility for extended signals + * in case 254 different valies is not enough + */ + break; + default: + break; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Re-adding parent control handler pipe to the scheduler\n"); + GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_DISK_pipe_handle (control_pipe, GNUNET_DISK_PIPE_END_READ), GNUNET_OS_parent_control_handler, control_pipe); + } + } } #endif +void +GNUNET_OS_install_parent_control_handler (void *cls, + const struct + GNUNET_SCHEDULER_TaskContext * tc) +{ +#ifdef WINDOWS + char *env_buf; + char *endptr; + HANDLE control_pipe_end[2]; + struct GNUNET_DISK_PipeHandle *control_pipe = NULL; + env_buf = getenv (GNUNET_OS_NT_CONTROL_PIPE); + if (env_buf == NULL || strlen (env_buf) <= 0 || env_buf[0] < '0' || env_buf[0] > '9') + return; + + control_pipe_end[0] = (HANDLE) strtol (env_buf, &endptr, 10); + control_pipe_end[1] = INVALID_HANDLE_VALUE; + + control_pipe = GNUNET_DISK_pipe_from_internal_handles_ (GNUNET_NO, &control_pipe_end[0], &control_pipe_end[1], sizeof (HANDLE)); + if (control_pipe == NULL) + return; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding parent control handler pipe to the scheduler\n"); + GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_DISK_pipe_handle (control_pipe, GNUNET_DISK_PIPE_END_READ), GNUNET_OS_parent_control_handler, control_pipe); +#endif +} + /** * Get process structure for current process * @@ -66,7 +133,7 @@ current_process.pid = GetCurrentProcessId (); current_process.handle = GetCurrentProcess (); #else - current_process.pid = 0; + current_process.pid = getpid (); #endif return ¤t_process; } @@ -75,27 +142,49 @@ GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig) { #if WINDOWS - if (sig == SIGKILL || sig == SIGTERM) + unsigned char c; + DWORD dwresult, error_code = NO_ERROR; + BOOL bresult = 1; + + switch (sig) { - HANDLE h = proc->handle; - if (NULL == h) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("Invalid process information {%d, %08X}\n"), - proc->pid, - h); + case SIGKILL: + c = 1; + break; + case SIGTERM: + c = 0; + break; + default: + errno = EINVAL; return -1; - } - if (!TerminateProcess (h, 0)) + } + + if (GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (proc->control_pipe, GNUNET_DISK_PIPE_END_WRITE), &c, sizeof (c)) != sizeof (c)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to write into control pipe, errno is %d\n", errno); + bresult = 0; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Wrote control code into control pipe, now waiting\n"); + SetLastError (0); + dwresult = WaitForSingleObject (proc->handle, 4*1000); + error_code = GetLastError (); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Woke up, returned %d, GLE is %d\n", dwresult, error_code); + if (WAIT_OBJECT_0 != dwresult || error_code != NO_ERROR) { - SetErrnoFromWinError (GetLastError ()); - return -1; + SetLastError (0); + bresult = TerminateProcess (proc->handle, 0); + error_code = GetLastError (); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TerminateProcess for the child returned %d, GLE is %d\n", bresult, error_code); } - else - return 0; } - errno = EINVAL; - return -1; + if (error_code != NO_ERROR || !bresult) + { + return -1; + } + else + return 0; #else return kill (proc->pid, sig); #endif @@ -363,19 +452,32 @@ STARTUPINFO start; PROCESS_INFORMATION proc; struct GNUNET_OS_Process *gnunet_proc = NULL; + struct GNUNET_DISK_PipeHandle *control_pipe = NULL; + char *env_buf; HANDLE stdin_handle; HANDLE stdout_handle; + HANDLE control_pipe_read_end, control_pipe_write_end; char path[MAX_PATH + 1]; - cmdlen = 0; + if ((HINSTANCE) 32 >= FindExecutableA (filename, NULL, path)) + { + SetErrnoFromWinError (GetLastError ()); + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "FindExecutable", filename); + return NULL; + } + + cmdlen = strlen (path) + 3; va_start (ap, filename); while (NULL != (arg = va_arg (ap, char *))) + { cmdlen = cmdlen + strlen (arg) + 3; + } va_end (ap); cmd = idx = GNUNET_malloc (sizeof (char) * (cmdlen + 1)); + idx += sprintf (idx, "\"%s\" ", path); va_start (ap, filename); while (NULL != (arg = va_arg (ap, char *))) idx += sprintf (idx, "\"%s\" ", arg); @@ -399,30 +501,42 @@ start.hStdOutput = stdout_handle; } - if (32 >= FindExecutableA (filename, NULL, path)) - { - SetErrnoFromWinError (GetLastError ()); - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "FindExecutable", filename); - return NULL; - } + control_pipe = GNUNET_DISK_pipe (GNUNET_NO, 1, 0); + GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (control_pipe, GNUNET_DISK_PIPE_END_READ), &control_pipe_read_end, sizeof (HANDLE)); + GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (control_pipe, GNUNET_DISK_PIPE_END_WRITE), &control_pipe_write_end, sizeof (HANDLE)); + GNUNET_asprintf (&env_buf, "%s=%d", GNUNET_OS_NT_CONTROL_PIPE, control_pipe_read_end); + putenv (env_buf); + GNUNET_free (env_buf); + if (!CreateProcessA (path, cmd, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &start, &proc)) { SetErrnoFromWinError (GetLastError ()); GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "CreateProcess", path); - return NULL; + goto end; } gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); gnunet_proc->pid = proc.dwProcessId; gnunet_proc->handle = proc.hProcess; + gnunet_proc->control_pipe = control_pipe; CreateThread (NULL, 64000, ChildWaitThread, (void *) gnunet_proc, 0, NULL); CloseHandle (proc.hThread); +end: + GNUNET_asprintf (&env_buf, "%s=", GNUNET_OS_NT_CONTROL_PIPE); + putenv (env_buf); + GNUNET_free (env_buf); + + if (gnunet_proc == NULL) + GNUNET_DISK_pipe_close (control_pipe); + else + GNUNET_DISK_pipe_close_end (control_pipe, GNUNET_DISK_PIPE_END_READ); + GNUNET_free (cmd); return gnunet_proc; @@ -551,12 +665,14 @@ PROCESS_INFORMATION proc; int argcount = 0; char non_const_filename[MAX_PATH +1]; - int filenamelen = 0; struct GNUNET_OS_Process *gnunet_proc = NULL; + struct GNUNET_DISK_PipeHandle *control_pipe = NULL; + char *env_buf; + HANDLE control_pipe_read_end, control_pipe_write_end; GNUNET_assert (lsocks == NULL); - if (32 >= FindExecutableA (filename, NULL, non_const_filename)) + if ((HINSTANCE) 32 >= FindExecutableA (filename, NULL, non_const_filename)) { SetErrnoFromWinError (GetLastError ()); GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "FindExecutable", filename); @@ -579,7 +695,12 @@ arg = (char **) argv; while (*arg) { - non_const_argv[argcount] = GNUNET_strdup (*arg); + if (argcount == 0) + /* Otherwise we'll get the argv[0] without .exe extension, + that will break libtool wrapper */ + non_const_argv[argcount] = GNUNET_strdup (non_const_filename); + else + non_const_argv[argcount] = GNUNET_strdup (*arg); arg++; argcount++; } @@ -606,22 +727,43 @@ memset (&start, 0, sizeof (start)); start.cb = sizeof (start); - if (!CreateProcess - (non_const_filename, cmd, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &start, + control_pipe = GNUNET_DISK_pipe (GNUNET_NO, 1, 0); + GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (control_pipe, GNUNET_DISK_PIPE_END_READ), &control_pipe_read_end, sizeof (HANDLE)); + GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (control_pipe, GNUNET_DISK_PIPE_END_WRITE), &control_pipe_write_end, sizeof (HANDLE)); + + + GNUNET_asprintf (&env_buf, "%s=%d", GNUNET_OS_NT_CONTROL_PIPE, control_pipe_read_end); + putenv (env_buf); + GNUNET_free (env_buf); + + if (!CreateProcessA + (non_const_filename, cmd, NULL, NULL, TRUE, + DETACHED_PROCESS, NULL, NULL, &start, &proc)) { SetErrnoFromWinError (GetLastError ()); GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "CreateProcess"); - return NULL; + goto end; } gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); gnunet_proc->pid = proc.dwProcessId; gnunet_proc->handle = proc.hProcess; + gnunet_proc->control_pipe = control_pipe; CreateThread (NULL, 64000, ChildWaitThread, (void *) gnunet_proc, 0, NULL); CloseHandle (proc.hThread); +end: + GNUNET_asprintf (&env_buf, "%s=", GNUNET_OS_NT_CONTROL_PIPE); + putenv (env_buf); + GNUNET_free (env_buf); + + if (gnunet_proc == NULL) + GNUNET_DISK_pipe_close (control_pipe); + else + GNUNET_DISK_pipe_close_end (control_pipe, GNUNET_DISK_PIPE_END_READ); + GNUNET_free (cmd); while (argcount > 0) Index: src/util/network.c =================================================================== --- src/util/network.c (revision 13603) +++ src/util/network.c (working copy) @@ -470,8 +470,8 @@ #ifdef MSG_DONTWAIT flags |= MSG_DONTWAIT; +#endif -#endif ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen); #ifdef MINGW if (SOCKET_ERROR == ret) @@ -1138,9 +1138,19 @@ { HANDLE h; - DWORD dwBytes; + DWORD dwBytes = 0, error_code; + BOOL bresult; h = *(HANDLE *) GNUNET_CONTAINER_slist_get (i, NULL); - if (!PeekNamedPipe (h, NULL, 0, NULL, &dwBytes, NULL)) + bresult = PeekNamedPipe (h, NULL, 0, NULL, &dwBytes, NULL); + error_code = GetLastError (); + /* FIXME: This should fail when the pipe is _really_ invalid, + * should skip the pipe if the error means that it's + * temporarily unavailable, and should succeed if the pipe + * is broken (or that the otherwise valid pipe is in a condition + * that prevents further reading). + * For now it succeeds only when the pipe is broken or readable. + */ + if (!bresult && error_code != ERROR_BROKEN_PIPE) { retcode = -1; SetErrnoFromWinError (GetLastError ()); @@ -1152,7 +1162,7 @@ #endif goto select_loop_end; } - else if (dwBytes) + else if (dwBytes || error_code == ERROR_BROKEN_PIPE) { GNUNET_CONTAINER_slist_add (handles_read, Index: src/util/disk.c =================================================================== --- src/util/disk.c (revision 13603) +++ src/util/disk.c (working copy) @@ -1910,4 +1910,95 @@ return GNUNET_OK; } +struct GNUNET_DISK_FileHandle +GNUNET_DISK_file_from_internal_handle_ (void *src, size_t src_len) +{ + struct GNUNET_DISK_FileHandle ret; +#ifdef MINGW + if (src_len == sizeof (HANDLE)) + ret.h = *(HANDLE *) src; + else + ret.h = INVALID_HANDLE_VALUE; +#else + if (src_len == sizeof (int)) + ret.fd = *(int *) src; + else + ret.fd = -1; +#endif + return ret; +} + +struct GNUNET_DISK_PipeHandle * +GNUNET_DISK_pipe_from_internal_handles_ (int blocking, void *src0, void *src1, size_t src_len) +{ + struct GNUNET_DISK_PipeHandle *p; + struct GNUNET_DISK_FileHandle *fds; + + p = + GNUNET_malloc (sizeof (struct GNUNET_DISK_PipeHandle) + + 2 * sizeof (struct GNUNET_DISK_FileHandle)); + fds = (struct GNUNET_DISK_FileHandle *) &p[1]; + p->fd[0] = &fds[0]; + p->fd[1] = &fds[1]; + fds[0] = GNUNET_DISK_file_from_internal_handle_ (src0, src_len); + fds[1] = GNUNET_DISK_file_from_internal_handle_ (src1, src_len); +#ifndef MINGW + int fd[2]; + int ret; + int flags; + int eno; + + fd[0] = fds[0].fd; + fd[1] = fds[1].fd; + ret = 0; + if (fd[0] >= 0) + { + flags = fcntl (fd[0], F_GETFL); + if (!blocking) + flags |= O_NONBLOCK; + if (0 > fcntl (fd[0], F_SETFL, flags)) + ret = -1; + flags = fcntl (fd[0], F_GETFD); + flags |= FD_CLOEXEC; + if (0 > fcntl (fd[0], F_SETFD, flags)) + ret = -1; + } + if (fd[1] >= 0) + { + flags = fcntl (fd[1], F_GETFL); + if (!blocking) + flags |= O_NONBLOCK; + if (0 > fcntl (fd[1], F_SETFL, flags)) + ret = -1; + flags = fcntl (fd[1], F_GETFD); + flags |= FD_CLOEXEC; + if (0 > fcntl (fd[1], F_SETFD, flags)) + ret = -1; + } + if (ret == -1) + { + eno = errno; + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fcntl"); + GNUNET_free (p); + errno = eno; + return NULL; + } +#else + /* Empirical fact: DuplicateHandle() on a handle inherited from the parent + * dies with ERROR_INVALID_HANDLE, so we won't try to duplicate these to + * make them inheritable/uninheritable. + */ + if (!blocking) + { + DWORD mode; + + mode = PIPE_NOWAIT; + SetNamedPipeHandleState (p->fd[0]->h, &mode, NULL, NULL); + SetNamedPipeHandleState (p->fd[1]->h, &mode, NULL, NULL); + /* this always fails on Windows 95, so we don't care about error handling */ + } +#endif + return p; +} + /* end of disk.c */ Index: src/util/connection.c =================================================================== --- src/util/connection.c (revision 13603) +++ src/util/connection.c (working copy) @@ -461,7 +461,7 @@ struct GNUNET_CONNECTION_Handle *sock = cls; GNUNET_CONNECTION_TransmitReadyNotify notify; struct AddressProbe *pos; - + sock->destroy_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (sock->dns_active == NULL); if (0 != (sock->ccs & COCO_TRANSMIT_READY)) @@ -497,7 +497,11 @@ "Shutting down socket (%p)\n", sock); #endif if (sock->persist != GNUNET_YES) - GNUNET_NETWORK_socket_shutdown (sock->sock, SHUT_RDWR); + { + if (GNUNET_YES != GNUNET_NETWORK_socket_shutdown (sock->sock, SHUT_RDWR)) + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Socket shutdown didn't go well, errno is %d\n", errno); + } } if (sock->read_task != GNUNET_SCHEDULER_NO_TASK) { @@ -945,6 +949,7 @@ struct GNUNET_NETWORK_Handle *s; struct GNUNET_CONNECTION_Handle *ret; + s = GNUNET_NETWORK_socket_create (af_family, SOCK_STREAM, 0); if (s == NULL) { Index: src/util/disk.h =================================================================== --- src/util/disk.h (revision 13603) +++ src/util/disk.h (working copy) @@ -1,75 +1,71 @@ -/* - This file is part of GNUnet. - (C) 2009 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 2, 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 util/disk.h - * @brief Internal DISK related helper functions - * @author Nils Durner - */ - - -#ifndef GNUNET_DISK_H_ -#define GNUNET_DISK_H_ - -#include "gnunet_disk_lib.h" - - -/** - * Handle used to access files (and pipes). - */ -struct GNUNET_DISK_FileHandle +/* + This file is part of GNUnet. + (C) 2009 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 2, 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 util/disk.h + * @brief Internal DISK related helper functions + * @author Nils Durner + */ + +#ifndef GNUNET_DISK_H_ +#define GNUNET_DISK_H_ + +#include "gnunet_disk_lib.h" + +/** + * Handle used to access files (and pipes). + */ +struct GNUNET_DISK_FileHandle { - -#ifdef MINGW - /** - * File handle under W32. - */ + +#ifdef MINGW + /** + * File handle under W32. + */ HANDLE h; - + #else /* */ - /** - * File handle on other OSes. - */ + /** + * File handle on other OSes. + */ int fd; - + #endif /* */ }; - - - - -/** - * Retrieve OS file handle - * - * @internal - * @param fh GNUnet file descriptor - * @param dst destination buffer - * @param dst_len length of dst - * @return GNUNET_OK on success, GNUNET_SYSERR otherwise - */ + +/** + * Retrieve OS file handle + * + * @internal + * @param fh GNUnet file descriptor + * @param dst destination buffer + * @param dst_len length of dst + * @return GNUNET_OK on success, GNUNET_SYSERR otherwise + */ int GNUNET_DISK_internal_file_handle_ (const struct GNUNET_DISK_FileHandle *fh, void *dst, size_t dst_len); - - -#endif /* GNUNET_DISK_H_ */ + +struct GNUNET_DISK_PipeHandle *GNUNET_DISK_pipe_from_internal_handles_ (int blocking, void *src0, void *src1, size_t src_len); + +#endif /* GNUNET_DISK_H_ */