gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r8864 - in gnunet: . doc/man src/fs src/include src/util


From: gnunet
Subject: [GNUnet-SVN] r8864 - in gnunet: . doc/man src/fs src/include src/util
Date: Fri, 28 Aug 2009 03:05:15 -0600

Author: grothoff
Date: 2009-08-28 03:05:15 -0600 (Fri, 28 Aug 2009)
New Revision: 8864

Added:
   gnunet/doc/man/gnunet-publish.1
   gnunet/src/fs/gnunet-publish.c
   gnunet/src/util/network_socket.c
Removed:
   gnunet/src/util/sock.c
Modified:
   gnunet/TODO
   gnunet/doc/man/Makefile.am
   gnunet/src/fs/Makefile.am
   gnunet/src/fs/fs.h
   gnunet/src/fs/fs_directory.c
   gnunet/src/fs/fs_getopt.c
   gnunet/src/fs/fs_publish.c
   gnunet/src/include/gnunet_connection_lib.h
   gnunet/src/include/gnunet_container_lib.h
   gnunet/src/include/gnunet_fs_service.h
   gnunet/src/include/gnunet_network_lib.h
   gnunet/src/util/Makefile.am
   gnunet/src/util/container_meta_data.c
Log:
stuff

Modified: gnunet/TODO
===================================================================
--- gnunet/TODO 2009-08-27 11:14:19 UTC (rev 8863)
+++ gnunet/TODO 2009-08-28 09:05:15 UTC (rev 8864)
@@ -44,20 +44,18 @@
     + persistence mechanism (design done)
     + sharing API
       ~ file-information (needs testing)
-      ~ directory: implement new directory builder!
-      ~ insert: close, need directory builder first!
-      ~ unindex & list indexed!!!
-      ~ search
-      ~ download
+      ~ directory (needs testing)
+      ~ publish (work in progress...)
+      ~ unindex & list indexed!!! (need publish to be done)
+      ~ search (need publish to be done)
+      ~ download (need publish/search to be done)
       ~ namespaces
       ~ collection
   - design network structs (P2P)
   - datastore request queueing mechanism
   - implement FS service (needs DHT)
-    + insert
     + download
     + search
-    + unindex
   - implement testcases 
     + URI API
     + getopt API

Modified: gnunet/doc/man/Makefile.am
===================================================================
--- gnunet/doc/man/Makefile.am  2009-08-27 11:14:19 UTC (rev 8863)
+++ gnunet/doc/man/Makefile.am  2009-08-28 09:05:15 UTC (rev 8864)
@@ -1,6 +1,7 @@
 man_MANS = \
   gnunet-arm.1 \
   gnunet-peerinfo.1 \
+  gnunet-publish.1 \
   gnunet-statistics.1 \
   gnunet-transport.c
 

Added: gnunet/doc/man/gnunet-publish.1
===================================================================
--- gnunet/doc/man/gnunet-publish.1                             (rev 0)
+++ gnunet/doc/man/gnunet-publish.1     2009-08-28 09:05:15 UTC (rev 8864)
@@ -0,0 +1,166 @@
+.TH GNUNET-PUBLISH "1" "27 Aug 2009" "GNUnet"
+.SH NAME
+gnunet\-publish \- a command line interface for publishing new content into 
GNUnet
+.SH SYNOPSIS
+.B gnunet\-publish
+[\fIOPTIONS\fR] FILENAME
+.SH DESCRIPTION
+.PP
+In order to share files with other GNUnet users, the files must first be made 
available to GNUnet.  GNUnet does not automatically share all files from a 
certain directory.  In fact, even files that are downloaded are not 
automatically shared.
+.PP
+In order to start sharing files, the files must be added either using 
gnunet\-publish or a graphical interface such as gnunet\-gtk.  The command line 
tool gnunet\-publish is more useful if many files are supposed to be added.  
gnunet\-publish can automatically publish batches of files, recursively publish 
directories, create directories that can be browsed within GNUnet and publish 
file lists in a namespace.  When run on a directory, gnunet\-publish will 
always recursively publish all of the files in the directory.
+.PP
+gnunet\-publish can automatically extract keywords from the files that are 
shared.  Users that want to download files from GNUnet use keywords to search 
for the appropriate content.  You can disable keyword extraction with the \-D 
option.  You can manually add keywords using the \-k option. The keywords are 
case\-sensitive. (However, keyword normalization can also be used.)
+.PP
+You can use automatic meta\-data extraction (based on libextractor) or the 
command\-line option \-m to specify meta-data.  For the \-m option you need to 
use the form keyword\-type:value.  For example, use "\-m os:Linux" to specify 
that the operating system is Linux.  Common meta\-data types are "author", 
"title" , "mimetype", "filename", "language", "subject" and "keywords".  A full 
list can be obtained from the extract tool using the option \-\-list.  The 
meta\-data is used to help users in searching for files on the network.  
+.PP
+In addition to searching for files by keyword, GNUnet allows organizing files 
into directories.  With directories, the user only needs to find the directory 
in order to be able to download any of the files listed in the directory.  
Directories can contain pointers to other directories.
+.PP
+With gnunet\-publish, it is easy to create new directories simultaneously when 
adding the files.  Simply pass the name of a directory instead of a file.
+.PP
+Since keywords can be spammed (any user can add any content under any 
keyword), GNUnet supports namespaces.  A namespace is a subset of the 
searchspace into which only the holder of a certain pseudonym can add content.  
Any GNUnet user can create any number of pseudonyms using 
\fBgnunet\-pseudonym\fR. Pseudonyms are stored in the user's GNUnet directory. 
While pseudonyms are locally identified with an arbitrary string that the user 
selects when the pseudonym is created, the namespace is globally known only 
under the hash of the public key of the pseudonym. Since only the owner of the 
pseudonym can add content to the namespace, it is impossible for other users to 
pollute the namespace. gnunet\-publish automatically publishs the 
top\-directory (or the only file if only one file is specified) into the 
namespace if a pseudonym is specified.
+.PP
+It is possible to update content in GNUnet if that content was placed and 
obtained from a particular namespace.  Updates are only possible for content in 
namespaces since this is the only way to assure that a malicious party can not 
supply counterfeited updates.  Note that an update with GNUnet does not make 
the old content unavailable, GNUnet merely allows the publisher to point users 
to more recent versions. You can use the \-N option to specify the future 
identifier of an update.  When using this option, a GNUnet client that finds 
the current (\-t) identifier will automatically begin a search for the update 
(\-N) identifier.  If you later publish an update under the (\-N) identifier, 
both results will be given to the user. 
+.PP
+You can use automatic meta\-data extraction (based on libextractor) or the 
command\-line option \-m to specify meta-data.  For the \-m option you need to 
use the form keyword\-type:value.  For example, use "\-m os:Linux" to specify 
that the operating system is Linux.  Common meta\-data types are "author", 
"title" , "mimetype", "filename", "language", "subject" and "keywords".  A full 
list can be obtained from the extract tool using the option \-\-list.  The 
meta\-data is used to help users in searching for files on the network.  The 
keywords are case\-sensitive.
+.PP
+GNUnet supports two styles of publishing files on the network. Publishing a 
file means that a copy of the file is made in the local (!) database of the 
node.  Indexing a file means that an index is added to the local (!)  database 
with symbolic links to the file itself.  The links will use the SHA-512 hash of 
the entire file as the filename.  Indexing is generally significantly more 
efficient and the default choice.  However, indexing only works if the indexed 
file can be read (using the same absolute path) by gnunetd.  If this is not the 
case, indexing will fail (and gnunet\-publish will automatically revert to 
publishing instead).  Regardless of which method is used to publish the file, 
the file will be slowly (depending on how often it is requested and on how much 
bandwidth is available) dispersed into the network.  If you publish or index a 
file and then leave the network, it will almost always NOT be available anymore.
+
+\fB\-c \fIFILENAME\fR, \fB\-\-config=FILENAME\fR
+Use alternate config file (if this option is not specified, the default is 
~/.gnunet/gnunet.conf).
+
+.TP
+\fB\-D\fR, \fB\-\-disable\-extractor\fR 
+Disable use of GNU libextractor for finding additional keywords and metadata.
+
+.TP
+\fB\-e\fR, \fB\-\-extract\fR
+Print the list of keywords that will be used for each file given the current 
options.  Do not perform any indexing or publishing.
+
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print a brief help page with all the options.
+
+.TP
+\fB\-H \fIHOSTNAME\fR, \fB\-\-host=\fIHOSTNAME\fR
+on which host is gnunetd running (default: localhost).  You can also specify a 
port using the syntax HOSTNAME:PORT.  The default port is 2087. 
+.TP
+\fB\-k \fIKEYWORD\fR, \fB\-\-key=KEYWORD\fR
+additional key to index the content with (to add multiple keys, specify 
multiple times). Each additional key is case\-sensitive. Can be specified 
multiple times.  The keyword is only applied to the top\-level file or 
directory.
+
+.TP
+\fB\-L \fILOGLEVEL\fR, \fB\-\-loglevel=\fILOGLEVEL\fR
+Change the loglevel.  Possible values for LOGLEVEL are NOTHING, FATAL,
+ERROR, WARNING, INFO, STATUS and DEBUG.  Note that options in the 
+configuration file take precedence over this option (the argument 
+will be ignored in that case).
+
+.TP
+\fB\-m \fITYPE:VALUE\fR, \fB\-\-meta=\fITYPE:VALUE\fR
+For the main file (or directory), set the metadata of the given TYPE to the 
given VALUE.  Note that this will not add the respective VALUE to the set of 
keywords under which the file can be found.
+
+.TP
+\fB\-n\fR, \fB\-\-noindex\fR
+Executive summary: You probably don't need it.
+
+Do not index, full publishion.  Note that directories, RBlocks, SBlocks and 
IBlocks are always published (even without this option).  With this option, 
every block of the actual files is stored in encrypted form in the block 
database of the local peer.  While this adds security if the local node is 
compromised (the adversary snags your machine), it is significantly less 
efficient compared to on\-demand encryption and is definitely not recommended 
for large files.
+
+.TP
+\fB\-N \fIID\fR, \fB\-\-next=\fIID\fR
+Specifies the next ID of a future version of the SBlock.  This option is only 
valid together with the \-P option.  This option can be used to specify what 
the identifier of an updated version will look like.  Note that specifying \-i 
and \-N without \-t is not allowed.
+
+.TP
+\fB\-p \fIPRIORITY\fR, \fB\-\-prio=\fIPRIORITY\fR
+Executive summary: You probably don't need it.
+
+Set the priority of the published content (default: 365).  If the local 
database is full, GNUnet will discard the content with the lowest ranking.  
Note that ranks change over time depending on popularity.  The default should 
be high enough to preserve the locally published content in favor of content 
that migrates from other peers.
+
+.TP
+\fB\-P \fINAME\fR, \fB\-\-pseudonym=\fINAME\fR
+For the top\-level directory or file, create an SBlock that places the file 
into the namespace specified by the pseudonym NAME.
+
+.TP
+\fB\-s\fR, \fB\-\-simulate-only\fR
+When this option is used, gnunet\-publish will not actually publish the file 
but just simulate what would be done.  This can be used to compute the GNUnet 
URI for a file without actually sharing it.
+
+.TP
+\fB\-t \fIID\fR, \fB\-\-this=\fIID\fR
+Specifies the ID of the SBlock.  This option is only valid together with the\ 
\-s option.
+
+.TP
+\fB\-u \fIURI\fR, \fB\-\-uri=\fIURI\fR
+This option can be used to specify the URI of a file instead of a filename 
(this is the only case where the otherwise mandatory filename argument must be 
omitted).  Instead of publishing a file or directory and using the 
corresponding URI, gnunet\-publish will use this URI and perform the selected 
namespace or keyword operations.  This can be used to add additional keywords 
to a file that has already been shared or to add files to a namespace for which 
the URI is known but the content is not locally available.
+
+.TP
+\fB\-v\fR, \fB\-\-version\fR
+Print the version number.
+
+.TP
+\fB\-V\fR, \fB\-\-verbose\fR
+Be verbose.  Using this option causes gnunet\-publish to print progress 
information and at the end the file identification that can be used to download 
the file from GNUnet.
+
+
+.SH EXAMPLES
+.PP
+
+\fBBasic examples\fR
+
+Index a file COPYING:
+
+ # gnunet\-publish COPYING
+
+Publish a file COPYING:
+
+ # gnunet\-publish \-n COPYING
+
+Index a file COPYING with the keywords \fBgpl\fR and \fBtest\fR:
+
+ # gnunet\-publish \-k gpl \-k test COPYING
+
+Index a file COPYING with description "GNU License", mime-type "text/plain" 
and keywords \fBgpl\fR and \fBtest\fR:
+
+ # gnunet\-publish \-m "description:GNU License" \-k gpl \-k test -m 
"mimetype:text/plain" COPYING
+
+\fBUsing directories\fR
+
+Index the files COPYING and AUTHORS with keyword \fBtest\fR and build a 
directory containing the two files.  Make the directory itself available under 
keyword \fBgnu\fR and disable keyword extraction using libextractor:
+
+ # mkdir gnu
+ # mv COPYING AUTHORS gnu/
+ # gnunet\-publish \-K test \-k gnu \-D gnu/
+
+Neatly publish an image gallery in \fBkittendir/\fR and its subdirs with 
keyword \fBkittens\fR for the directory but no keywords for the individual 
files or subdirs (\-n).  Force description for all files:
+
+ # gnunet\-publish \-n \-m "description:Kitten collection" \-k kittens 
kittendir/
+
+\fBSecure publishing with namespaces\fR
+
+Publish file COPYING with pseudonym RIAA-2 (\-P) and with identifier \fBgpl\fR 
(\-t) and no updates:
+
+ # gnunet\-publish \-P RIAA-2 \-t gpl COPYING
+
+Recursively index /home/ogg and build a matching directory structure. Publish 
the top\-level directory into the namespace under the pseudonym RIAA-2 (\-P) 
under identifier 'MUSIC' (\-t) and promise to provide an update with identifier 
'VIDEOS' (\-N):
+
+ # gnunet\-publish \-P RIAA-2 \-t MUSIC \-N VIDEOS /home/ogg
+
+Recursively publish (\-n) /var/lib/mysql and build a matching directory 
structure, but disable the use of libextractor to extract keywords (\-n).  
Print the file identifiers (\-V) that can be used to retrieve the files.  This 
will store a copy of the MySQL database in GNUnet but without adding any 
keywords to search for it.  Thus only people that have been told the secret 
file identifiers printed with the \-V option can retrieve the (secret?) files:
+
+ # gnunet\-publish \-nV /var/lib/mysql
+
+Create a namespace entry 'root' in namespace MPAA-1 and announce that the next 
update will be called 'next':
+
+ # gnunet\-publish \-P MPAA-1 -t root \-N next noise.mp3
+
+Update the previous entry, do not allow any future updates:
+
+ # gnunet\-publish \-P MPAA-1 \-t next noise_updated.mp3
+
+
+.SH FILES
+.TP
+~/.gnunet/gnunet.conf
+GNUnet configuration file
+.SH "REPORTING BUGS"
+Report bugs by using mantis <https://gnunet.org/mantis/> or by sending 
electronic mail to <address@hidden>
+.SH "SEE ALSO"
+\fBgnunet\-auto\-share\fP(1), \fBgnunet\-gtk\fP(1), 
\fBgnunet\-pseudonym\fP(1), \fBgnunet\-search\fP(1), \fBgnunet\-download\fP(1), 
\fBgnunet.conf\fP(5), \fBgnunetd\fP(1), \fBextract\fP(1)

Modified: gnunet/src/fs/Makefile.am
===================================================================
--- gnunet/src/fs/Makefile.am   2009-08-27 11:14:19 UTC (rev 8863)
+++ gnunet/src/fs/Makefile.am   2009-08-28 09:05:15 UTC (rev 8864)
@@ -26,6 +26,7 @@
   fs_uri.c 
 
 libgnunetfs_la_LIBADD = \
+  $(top_builddir)/src/datastore/libgnunetdatastore.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   -lextractor \
   $(GN_LIBINTL) $(XLIB)
@@ -35,11 +36,11 @@
   -version-info 0:0:0
 
 
-#bin_PROGRAMS =  
+bin_PROGRAMS = \
+  gnunet-publish 
 # gnunet-directory 
 # gnunet-download 
 # gnunet-pseudonym 
-# gnunet-publish 
 # gnunet-search
 # gnunet-unindex 
 
@@ -51,6 +52,14 @@
 #  $(GN_LIBINTL)
 
 
+gnunet_publish_SOURCES =  \
+ gnunet-publish.c         
+gnunet_publish_LDADD =  \
+ $(top_builddir)/src/fs/libgnunetfs.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(GN_LIBINTL)
+
+
 check_PROGRAMS = \
  test_fs_collection \
  test_fs_directory \

Modified: gnunet/src/fs/fs.h
===================================================================
--- gnunet/src/fs/fs.h  2009-08-27 11:14:19 UTC (rev 8863)
+++ gnunet/src/fs/fs.h  2009-08-28 09:05:15 UTC (rev 8864)
@@ -308,13 +308,13 @@
        * Size of the directory itself (in bytes); 0 if the
        * size has not yet been calculated.
        */
-      uint64_t dir_size;
+      size_t dir_size;
 
       /**
        * Pointer to the data for the directory (or NULL if not
        * available).
        */
-      char *dir_data;
+      void *dir_data;
 
     } dir;
 

Modified: gnunet/src/fs/fs_directory.c
===================================================================
--- gnunet/src/fs/fs_directory.c        2009-08-27 11:14:19 UTC (rev 8863)
+++ gnunet/src/fs/fs_directory.c        2009-08-28 09:05:15 UTC (rev 8864)
@@ -24,7 +24,6 @@
  * @author Christian Grothoff
  *
  * TODO:
- * - add support for embedded file data (use padding room!)
  * - modify directory builder API to support incremental
  *   generation of directories (to allow directories that
  *   would not fit into memory to be created)
@@ -42,6 +41,13 @@
 #endif
 
 /**
+ * String that is used to indicate that a file
+ * is a GNUnet directory.
+ */
+#define GNUNET_DIRECTORY_MAGIC "\211GND\r\n\032\n"
+
+
+/**
  * Does the meta-data claim that this is a directory?
  * Checks if the mime-type is that of a GNUnet directory.
  *
@@ -118,6 +124,7 @@
                                   void *dep_cls)
 {
   const char *cdata = data;
+  char *file_data;
   char *emsg;
   uint64_t pos;
   uint64_t align;
@@ -217,17 +224,18 @@
           return; /* malformed ! */
         }
       pos += mdSize;
-      // EXTRACTOR_GNUNET_FULL_DATA
-      /* FIXME: add support for embedded data */
       filename = GNUNET_CONTAINER_meta_data_get_by_type (md,
                                                         EXTRACTOR_FILENAME);
+      file_data = GNUNET_CONTAINER_meta_data_get_by_type (md,
+                                                         
EXTRACTOR_GNUNET_FULL_DATA);
       if (dep != NULL) 
          dep (dep_cls,
              filename,
              uri,
              md,
-             0,
-             NULL);
+             (file_data != NULL) ? strlen(file_data) : 0,
+             file_data);
+      GNUNET_free_non_null (file_data);
       GNUNET_free_non_null (filename);
       GNUNET_CONTAINER_meta_data_destroy (md);
       GNUNET_FS_uri_destroy (uri);
@@ -308,6 +316,7 @@
   struct BuilderEntry *e;
   uint64_t fsize;
   uint32_t big;
+  ssize_t ret;
   size_t mds;
   size_t mdxs;
   char *uris;
@@ -316,12 +325,12 @@
   struct GNUNET_CONTAINER_MetaData *meta;
   const struct GNUNET_CONTAINER_MetaData *meta_use;
 
-  GNUNET_assert (! GNUNET_FS_uri_ksk_test (uri));
+  GNUNET_assert (! GNUNET_FS_uri_test_ksk (uri));
   if (NULL != data)
-    if (GNUNET_FS_uri_chk_test (uri))
-      fsize = GNUNET_FS_uri_chk_get_size (uri);
+    if (GNUNET_FS_uri_test_chk (uri))
+      fsize = GNUNET_FS_uri_chk_get_file_size (uri);
     else
-      fsize = GNUNET_FS_uri_chk_get_size (GNUNET_FS_uri_loc_get_uri (uri));
+      fsize = GNUNET_FS_uri_chk_get_file_size (GNUNET_FS_uri_loc_get_uri 
(uri));
   else
     fsize = 0; /* not given */
   if (fsize > GNUNET_FS_MAX_INLINE_SIZE)
@@ -500,8 +509,8 @@
   uint32_t big;
 
   size = 8 + sizeof (uint32_t);
-  size += GNUNET_meta_data_get_serialized_size (bld->meta, 
-                                               GNUNET_SERIALIZE_FULL);
+  size += GNUNET_CONTAINER_meta_data_get_serialized_size (bld->meta, 
+                                                         
GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL);
   if (bld->count > 0)
     {
       sizes = GNUNET_malloc (bld->count * sizeof (size_t));
@@ -512,7 +521,7 @@
        {
          perm[i] = i;
          bes[i] = pos;
-         sizes[i] = pos->size;
+         sizes[i] = pos->len;
          pos = pos->next;
        }
     }  
@@ -534,22 +543,22 @@
   memcpy (data, GNUNET_DIRECTORY_MAGIC, 8);
   off = 8;
 
-  ret = GNUNET_CONTAINER_meta_data_serialize (meta,
-                                             &(*data)[off +
-                                                      sizeof (uint32_t)],
-                                             size - pos - sizeof (uint32_t),
-                                             GNUNET_SERIALIZE_FULL);
+  ret = GNUNET_CONTAINER_meta_data_serialize (bld->meta,
+                                             &data[off +
+                                                   sizeof (uint32_t)],
+                                             size - off - sizeof (uint32_t),
+                                             
GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL);
   GNUNET_assert (ret != -1);
   big = htonl (ret);  
-  memcpy (&(*data)[8], &big, sizeof (uint32_t));
-  pos += sizeof (uint32_t) + ret;
-  for (j = 0; j < count; j++)
+  memcpy (&data[8], &big, sizeof (uint32_t));
+  off += sizeof (uint32_t) + ret;
+  for (j = 0; j < bld->count; j++)
     {
       i = perm[j];
-      psize = pos;
-      pos += sizes[i];
-      pos = do_align (psize, pos);
-      memcpy (&data[pos - sizes[i]], 
+      psize = off;
+      off += sizes[i];
+      off = do_align (psize, off);
+      memcpy (&data[off - sizes[i]], 
              &(bes[i])[1],
              sizes[i]);
       GNUNET_free (bes[i]);
@@ -557,7 +566,7 @@
   GNUNET_free (sizes);
   GNUNET_free (perm);
   GNUNET_free (bes);
-  GNUNET_assert (pos == size);  
+  GNUNET_assert (off == size);  
   GNUNET_CONTAINER_meta_data_destroy (bld->meta);
   GNUNET_free (bld);
 }

Modified: gnunet/src/fs/fs_getopt.c
===================================================================
--- gnunet/src/fs/fs_getopt.c   2009-08-27 11:14:19 UTC (rev 8863)
+++ gnunet/src/fs/fs_getopt.c   2009-08-28 09:05:15 UTC (rev 8864)
@@ -42,7 +42,7 @@
  * @return GNUNET_OK on success
  */
 int
-GNUNET_FS_getopt_configure_set_keywords (struct 
GNUNET_GETOPT_CommandLineProcessorContext* ctx, 
+GNUNET_FS_getopt_set_keywords (struct 
GNUNET_GETOPT_CommandLineProcessorContext* ctx, 
                                         void *scls,
                                         const char *option,
                                         const char *value)
@@ -124,7 +124,7 @@
  * @return GNUNET_OK on success
  */
 int
-GNUNET_FS_getopt_configure_set_metadata (struct 
GNUNET_GETOPT_CommandLineProcessorContext* ctx, 
+GNUNET_FS_getopt_set_metadata (struct 
GNUNET_GETOPT_CommandLineProcessorContext* ctx, 
                                         void *scls,
                                         const char *option,
                                         const char *value)

Modified: gnunet/src/fs/fs_publish.c
===================================================================
--- gnunet/src/fs/fs_publish.c  2009-08-27 11:14:19 UTC (rev 8863)
+++ gnunet/src/fs/fs_publish.c  2009-08-28 09:05:15 UTC (rev 8864)
@@ -26,7 +26,6 @@
  * @author Christian Grothoff
  *
  * TODO:
- * - directory creation
  * - KBlocks
  * - SBlocks
  * - indexing support
@@ -119,6 +118,7 @@
  *
  * @param sc overall upload data
  * @param p file that the block belongs to (needed for options!)
+ * @param query what the block should be indexed under
  * @param blk encoded block to publish
  * @param blk_size size of the block
  * @param blk_type type of the block
@@ -127,15 +127,14 @@
 static void
 publish_block (struct GNUNET_FS_PublishContext *sc,
               struct GNUNET_FS_FileInformation *p,
+              const GNUNET_HashCode *query,
               const void* blk,
               uint16_t blk_size,
               uint32_t blk_type,
               GNUNET_SCHEDULER_Task cont)
 {
-  struct GNUNET_HashCode key;
+  struct PutContCtx * dpc_cls;
 
-  // FIXME: GNUNET_FS_get_key (blk_type, blk, blk_size, &key);
-  // (or add "key" as argument to reduce hashing?)
   dpc_cls = GNUNET_malloc(sizeof(struct PutContCtx));
   dpc_cls->cont = cont;
   dpc_cls->sc = sc;
@@ -146,8 +145,9 @@
   // a task ID!  
   GNUNET_DATASTORE_put (sc->dsh,
                        sc->rid,
-                       &key,
+                       query,
                        blk_size,
+                       blk,
                        blk_type,
                        p->priority,
                        p->anonymity,
@@ -280,7 +280,8 @@
                    uint64_t offset)
 {
   uint64_t bds;
-  unsigned  int ret;
+  unsigned int ret;
+  unsigned int i;
 
   bds = GNUNET_FS_DBLOCK_SIZE; /* number of bytes each CHK at level "i"
                                  corresponds to */
@@ -305,7 +306,7 @@
 publish_content (struct GNUNET_FS_PublishContext *sc,
                 struct GNUNET_FS_FileInformation *p)
 {
-  struct ContentHashKey *chk;
+  struct ContentHashKey *mychk;
   const void *pt_block;
   uint16_t pt_size;
   char *emsg;
@@ -315,6 +316,10 @@
   struct GNUNET_CRYPTO_AesInitializationVector iv;
   uint64_t size;
   unsigned int off;
+  struct GNUNET_FS_DirectoryBuilder *db;
+  struct GNUNET_FS_FileInformation *dirpos;
+  void *raw_data;
+  char *dd;
 
   // FIXME: figure out how to share this code
   // with unindex!
@@ -323,14 +328,47 @@
     {
       if (p->is_directory)
        {
-         /* FIXME: create function to create directory
-            and use that API here! */
-         GNUNET_FS_directory_create (&p->data.dir.dir_size,
-                                     &p->data.dir.dir_data,
-                                     p->meta,
-                                     &directory_entry_lister,
-                                     p->data.dir.entries);
-         size = p->data.dir.data_size;
+         db = GNUNET_FS_directory_builder_create (p->meta);
+         dirpos = p->data.dir.entries;
+         while (NULL != dirpos)
+           {
+             if (dirpos->is_directory)
+               {
+                 raw_data = dirpos->data.dir.dir_data;
+                 dirpos->data.dir.dir_data = NULL;
+               }
+             else
+               {
+                 raw_data = NULL;
+                 if ( (dirpos->data.file.file_size < 
GNUNET_FS_MAX_INLINE_SIZE) &&
+                      (dirpos->data.file.file_size > 0) )
+                   {
+                     raw_data = GNUNET_malloc (dirpos->data.file.file_size);
+                     emsg = NULL;
+                     if (dirpos->data.file.file_size !=
+                         dirpos->data.file.reader 
(dirpos->data.file.reader_cls,
+                                                   0,
+                                                   dirpos->data.file.file_size,
+                                                   raw_data,
+                                                   &emsg))
+                       {
+                         GNUNET_free_non_null (emsg);
+                         GNUNET_free (raw_data);
+                         raw_data = NULL;
+                       } 
+                   }
+               }
+             GNUNET_FS_directory_builder_add (db,
+                                              dirpos->chk_uri,
+                                              dirpos->meta,
+                                              raw_data);
+             GNUNET_free_non_null (raw_data);
+             dirpos = dirpos->next;
+           }
+         GNUNET_FS_directory_builder_finish (db,
+                                             &p->data.dir.dir_size,
+                                             &p->data.dir.dir_data);
+         size = p->data.dir.dir_size;
        }
       p->chk_tree_depth = compute_depth (size);
       p->chk_tree = GNUNET_malloc (p->chk_tree_depth * 
@@ -344,17 +382,24 @@
        {
          pt_size = GNUNET_MIN(GNUNET_FS_DBLOCK_SIZE,
                               p->data.dir.dir_size - p->publish_offset);
-         pt_block = &p->data.dir.dir_data[p->publish_offset];
+         dd = p->data.dir.dir_data;
+         pt_block = &dd[p->publish_offset];
        }
       else
        {
          pt_size = GNUNET_MIN(GNUNET_FS_DBLOCK_SIZE,
                               p->data.file.file_size - p->publish_offset);
-         p->data.file.reader (p->data.file.reader_cls,
-                              p->publish_offset,
-                              pt_size,
-                              iob,
-                              &emsg);
+         emsg = NULL;
+         if (pt_size !=
+             p->data.file.reader (p->data.file.reader_cls,
+                                  p->publish_offset,
+                                  pt_size,
+                                  iob,
+                                  &emsg))
+           {
+             // FIXME: abort with error "emsg"
+             GNUNET_free (emsg);
+           }
          pt_block = iob;
        }
     }
@@ -367,9 +412,9 @@
     }
   off = compute_chk_offset (p->chk_tree_depth - p->current_depth,
                            p->publish_offset);
-  chk = &p->chk_tree[(p->current_depth-1)*GNUNET_FS_CHK_PER_INODE+off];
-  GNUNET_CRYPTO_hash (pt_block, pt_size, &chk->key);
-  GNUNET_CRYPTO_hash_to_aes_key (&chk->key, &sk, &iv);
+  mychk = &p->chk_tree[(p->current_depth-1)*GNUNET_FS_CHK_PER_INODE+off];
+  GNUNET_CRYPTO_hash (pt_block, pt_size, &mychk->key);
+  GNUNET_CRYPTO_hash_to_aes_key (&mychk->key, &sk, &iv);
   GNUNET_CRYPTO_aes_encrypt (pt_block,
                             pt_size,
                             &sk,
@@ -379,13 +424,16 @@
   // between publish/unindex!  Parameterize & move this code!
   // FIXME: something around here would need to change
   // for indexing!
-  publish_block (sc, p, enc, pt_size, 
+  publish_block (sc, p, 
+                &mychk->query,
+                enc, 
+                pt_size, 
                 (p->current_depth == p->chk_tree_depth) 
                 ? GNUNET_DATASTORE_BLOCKTYPE_DBLOCK 
                 : GNUNET_DATASTORE_BLOCKTYPE_IBLOCK,
                 &do_upload);
   // FIXME: should call progress function somewhere here!
-  GNUNET_CRYPTO_hash (enc, pt_size, &chk->query);
+  GNUNET_CRYPTO_hash (enc, pt_size, &mychk->query);
   if (p->current_depth == p->chk_tree_depth) 
     { 
       p->publish_offset += pt_size;
@@ -404,9 +452,9 @@
   if (0 == p->current_depth)
     {
       p->chk_uri = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri));
-      p->chk_uri.type = chk;
-      p->chk_uri.data.chk.chk = p->chk_tree[0];
-      p->chk_uri.data.chk.file_length = size;
+      p->chk_uri->type = chk;
+      p->chk_uri->data.chk.chk = p->chk_tree[0];
+      p->chk_uri->data.chk.file_length = size;
       GNUNET_free (p->chk_tree);
       p->chk_tree = NULL;
     }
@@ -445,7 +493,8 @@
       publish_kblocks (sc, p);
       return;
     }
-  if (p->do_index)
+  if ( (!p->is_directory) &&
+       (p->data.file.do_index) )
     {
       // FIXME: need to pre-compute hash over
       // the entire file and ask FS to prepare
@@ -542,7 +591,7 @@
   GNUNET_FS_namespace_delete (sc->namespace, GNUNET_NO);
   GNUNET_free_non_null (sc->nid);  
   GNUNET_free_non_null (sc->nuid);
-  GNUNET_DATASTORE_disconnect (sc->dsh);
+  GNUNET_DATASTORE_disconnect (sc->dsh, GNUNET_NO);
   GNUNET_free (sc);
 }
 

Added: gnunet/src/fs/gnunet-publish.c
===================================================================
--- gnunet/src/fs/gnunet-publish.c                              (rev 0)
+++ gnunet/src/fs/gnunet-publish.c      2009-08-28 09:05:15 UTC (rev 8864)
@@ -0,0 +1,556 @@
+/*
+     This file is part of GNUnet.
+     (C) 2001, 2002, 2004, 2005, 2006, 2007, 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 fs/gnunet-publish.c
+ * @brief publishing files on GNUnet
+ * @author Christian Grothoff
+ * @author Krista Bennett
+ * @author James Blackwell
+ * @author Igor Wronsky
+ *
+ * TODO:
+ * - support for some options is still missing (uri argument, simulate)
+ * - progress callbacks not implemented (and need verbosity option)
+ * - clean shutdown is not implemented (stop ctx, etc.)
+ */
+#include "platform.h"
+#include "gnunet_fs_service.h"
+
+#define DEFAULT_EXPIRATION GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_YEARS, 2)
+
+static int ret;
+
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+static struct GNUNET_FS_Handle *ctx;
+
+static struct GNUNET_FS_PublishContext *pc;
+
+static struct GNUNET_TIME_Absolute start_time;
+
+static struct GNUNET_CONTAINER_MetaData *meta;
+
+static struct GNUNET_FS_Uri *topKeywords;
+
+static unsigned int anonymity = 1;
+
+static unsigned int priority = 365;
+
+static char *uri_string;
+
+static char *next_id;
+
+static char *this_id;
+
+static char *pseudonym;
+
+static int do_insert;
+
+static int disable_extractor;
+
+static int do_simulate;
+
+static int extract_only;
+
+static int do_disable_creation_time;
+
+
+/**
+ * Called by FS client to give information about the progress of an 
+ * operation.
+ *
+ * @param cls closure
+ * @param info details about the event, specifying the event type
+ *        and various bits about the event
+ * @return client-context (for the next progress call
+ *         for this operation; should be set to NULL for
+ *         SUSPEND and STOPPED events).  The value returned
+ *         will be passed to future callbacks in the respective
+ *         field in the GNUNET_FS_ProgressInfo struct.
+ */
+static void *
+progress_cb (void *cls,
+            const struct GNUNET_FS_ProgressInfo *info)
+{
+  return NULL;
+}
+
+
+/**
+ * Print metadata entries (except binary
+ * metadata and the filename).
+ *
+ * @param cls closure
+ * @param type type of the meta data
+ * @param data value of the meta data
+ * @return GNUNET_OK to continue to iterate, GNUNET_SYSERR to abort
+ */
+static int
+meta_printer (void *cls,
+             EXTRACTOR_KeywordType type,
+             const char *data)
+{
+  if ( (type == EXTRACTOR_FILENAME) ||
+       (EXTRACTOR_isBinaryType (type)) )
+    return GNUNET_OK;
+  fprintf (stdout, 
+          "%s - %s",
+          EXTRACTOR_getKeywordTypeAsString (type),
+          data);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Merge metadata entries (except binary
+ * metadata).
+ *
+ * @param cls closure, target metadata structure
+ * @param type type of the meta data
+ * @param data value of the meta data
+ * @return GNUNET_OK to continue to iterate, GNUNET_SYSERR to abort
+ */
+static int
+meta_merger (void *cls,
+            EXTRACTOR_KeywordType type,
+            const char *data)
+{
+  struct GNUNET_CONTAINER_MetaData *m = cls;
+  GNUNET_CONTAINER_meta_data_insert (m,
+                                    type, 
+                                    data);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Function called on all entries before the
+ * publication.  This is where we perform
+ * modifications to the default based on
+ * command-line options.
+ *
+ * @param cls closure
+ * @param fi the entry in the publish-structure
+ * @param length length of the file or directory
+ * @param m metadata for the file or directory (can be modified)
+ * @param uri pointer to the keywords that will be used for this entry (can be 
modified)
+ * @param anonymity pointer to selected anonymity level (can be modified)
+ * @param priority pointer to selected priority (can be modified)
+ * @param expirationTime pointer to selected expiration time (can be modified)
+ * @param client_info pointer to client context set upon creation (can be 
modified)
+ * @return GNUNET_OK to continue, GNUNET_NO to remove
+ *         this entry from the directory, GNUNET_SYSERR
+ *         to abort the iteration
+ */
+static int
+publish_inspector (void *cls,
+                  struct GNUNET_FS_FileInformation *fi,
+                  uint64_t length,
+                  struct GNUNET_CONTAINER_MetaData *m,
+                  struct GNUNET_FS_Uri **uri,
+                  unsigned int *anonymity,
+                  unsigned int *priority,
+                  struct GNUNET_TIME_Absolute *expirationTime,
+                  void **client_info)
+{
+  char *fn;
+  char *fs;
+  struct GNUNET_FS_Uri *new_uri;
+
+  if (! do_disable_creation_time)
+    GNUNET_CONTAINER_meta_data_add_publication_date (meta);
+  if (NULL != topKeywords)
+    {
+      new_uri = GNUNET_FS_uri_ksk_merge (topKeywords,
+                                        *uri);
+      GNUNET_FS_uri_destroy (*uri);
+      *uri = new_uri;
+      GNUNET_FS_uri_destroy (topKeywords);
+      topKeywords = NULL;
+    }
+  if (NULL != meta)
+    {
+      GNUNET_CONTAINER_meta_data_get_contents (meta,
+                                              &meta_merger,
+                                              m);
+      GNUNET_CONTAINER_meta_data_destroy (meta);
+      meta = NULL;
+    }
+  if (extract_only)
+    {
+      fn = GNUNET_CONTAINER_meta_data_get_by_type (meta,
+                                                  EXTRACTOR_FILENAME);
+      fs = GNUNET_STRINGS_byte_size_fancy (length);
+      fprintf (stdout,
+              _("Keywords for file `%s' (%s)\n"),
+              fn,
+              fs);
+      GNUNET_free (fn);
+      GNUNET_free (fs);
+      GNUNET_CONTAINER_meta_data_get_contents (meta,
+                                              &meta_printer,
+                                              NULL);
+      fprintf (stdout, "\n");
+    }
+  if (GNUNET_FS_meta_data_test_for_directory (meta))
+    GNUNET_FS_file_information_inspect (fi,
+                                       &publish_inspector,
+                                       NULL);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Main function that will be run by the scheduler.
+ *
+ * @param cls closure
+ * @param sched the scheduler to use
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be 
NULL!)
+ * @param cfg configuration
+ */
+static void
+run (void *cls,
+     struct GNUNET_SCHEDULER_Handle *sched,
+     char *const *args,
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  struct GNUNET_FS_FileInformation *fi;
+  struct GNUNET_FS_Namespace *namespace;
+  EXTRACTOR_ExtractorList *l;
+  char *ex;
+  char *emsg;
+  
+  /* check arguments */
+  if ( ( (uri_string == NULL) || (extract_only) ) 
+       && ( (args[0] == NULL) || (args[1] != NULL) ) )
+    {
+      printf (_
+              ("You must specify one and only one filename for insertion.\n"));
+      ret = -1;
+      return;
+    }
+  if ((uri_string != NULL) && (args[0] != NULL))
+    {
+      printf (_("You must NOT specify an URI and a filename.\n"));
+      ret = -1;
+      return;
+    }
+  if ((uri_string != NULL) && (extract_only))
+    {
+      printf (_("Cannot extract metadata from a URI!\n"));
+      ret = -1;
+      return;
+    }
+  if (pseudonym != NULL)
+    {
+      if (NULL == this_id)
+        {
+          fprintf (stderr,
+                   _("Option `%s' is required when using option `%s'.\n"),
+                   "-t", "-P");
+          ret = -1;
+          return;
+        }
+    }
+  else
+    {                           /* ordinary insertion checks */
+      if (NULL != next_id)
+        {
+          fprintf (stderr,
+                   _("Option `%s' makes no sense without option `%s'.\n"),
+                   "-N", "-P");
+          ret = -1;
+          return;
+        }
+      if (NULL != this_id)
+        {
+          fprintf (stderr,
+                   _("Option `%s' makes no sense without option `%s'.\n"),
+                   "-t", "-P");
+          ret = -1;
+         return;
+        }
+    }
+  if (args[0] == NULL)
+    {
+      fprintf (stderr,
+              _("Need the name of a file to publish!\n"));
+      ret = 1;
+      return;
+    }
+  cfg = c;
+  ctx = GNUNET_FS_start (sched,
+                        cfg,
+                        "gnunet-publish",
+                        &progress_cb,
+                        NULL);
+  if (NULL == ctx)
+    {
+      fprintf (stderr,
+              _("Could not initialize `%s' subsystem.\n"),
+              "FS");
+      ret = 1;
+      return;
+    }
+  namespace = NULL;
+  if (NULL != pseudonym)
+    {
+      namespace = GNUNET_FS_namespace_create (ctx,
+                                             pseudonym);
+      if (NULL == namespace)
+       {
+         fprintf (stderr,
+                  _("Could not create namespace `%s'\n"),
+                  pseudonym);
+         GNUNET_FS_stop (ctx);
+         ret = 1;
+         return;
+       }
+    }
+  if (NULL != uri_string)
+    {
+      // FIXME -- implement!
+      return;
+    }
+  start_time = GNUNET_TIME_absolute_get ();
+
+  l = NULL;
+  if (! disable_extractor)
+    {
+      l = EXTRACTOR_loadDefaultLibraries ();
+      if (GNUNET_OK ==
+         GNUNET_CONFIGURATION_get_value_string (cfg, "FS", "EXTRACTORS",
+                                                &ex))
+       {
+         if (strlen (ex) > 0)
+           l = EXTRACTOR_loadConfigLibraries (l, ex);
+         GNUNET_free (ex);
+       }
+    }
+  fi = GNUNET_FS_file_information_create_from_directory (NULL,
+                                                        args[0],
+                                                        
&GNUNET_FS_directory_scanner_default,
+                                                        l,
+                                                        !do_insert,
+                                                        anonymity,
+                                                        priority,
+                                                        
GNUNET_TIME_relative_to_absolute (DEFAULT_EXPIRATION),
+                                                        &emsg);
+  EXTRACTOR_removeAll (l);  
+  if (fi == NULL)
+    {
+      fprintf (stderr,
+              _("Could not publish `%s': %s\n"),
+              args[0],
+              emsg);
+      GNUNET_free (emsg);
+      if (namespace != NULL)
+       GNUNET_FS_namespace_delete (namespace, GNUNET_NO);
+      GNUNET_FS_stop (ctx);
+      ret = 1;
+      return;
+    }
+  GNUNET_FS_file_information_inspect (fi,
+                                     &publish_inspector,
+                                     NULL);
+  if (extract_only)
+    {
+      if (namespace != NULL)
+       GNUNET_FS_namespace_delete (namespace, GNUNET_NO);
+      GNUNET_FS_file_information_destroy (fi, NULL, NULL);
+      GNUNET_FS_stop (ctx);
+      return;
+    }
+  pc = GNUNET_FS_publish_start (ctx,
+                               NULL,
+                               fi,
+                               namespace,
+                               this_id,
+                               next_id);
+}
+
+
+/**
+ * gnunet-publish command line options
+ */
+static struct GNUNET_GETOPT_CommandLineOption options[] = {
+  {'a', "anonymity", "LEVEL",
+   gettext_noop ("set the desired LEVEL of sender-anonymity"),
+   1, &GNUNET_GETOPT_set_uint, &anonymity},
+  {'d', "disable-creation-time", NULL,
+   gettext_noop
+   ("disable adding the creation time to the metadata of the uploaded file"),
+   0, &GNUNET_GETOPT_set_one, &do_disable_creation_time},
+  {'D', "disable-extractor", NULL,
+   gettext_noop
+   ("do not use libextractor to add keywords or metadata"),
+   0, &GNUNET_GETOPT_set_one, &disable_extractor},
+  {'e', "extract", NULL,
+   gettext_noop
+   ("print list of extracted keywords that would be used, but do not perform 
upload"),
+   0, &GNUNET_GETOPT_set_one, &extract_only},
+  {'k', "key", "KEYWORD",
+   gettext_noop
+   ("add an additional keyword for the top-level file or directory"
+    " (this option can be specified multiple times)"),
+   1, &GNUNET_FS_getopt_set_keywords, &topKeywords},
+  // *: option not yet used... (can handle in a pass over FI)
+  {'m', "meta", "TYPE:VALUE",
+   gettext_noop ("set the meta-data for the given TYPE to the given VALUE"),
+   1, &GNUNET_FS_getopt_set_metadata, &meta},
+  {'n', "noindex", NULL,
+   gettext_noop ("do not index, perform full insertion (stores entire "
+                 "file in encrypted form in GNUnet database)"),
+   0, &GNUNET_GETOPT_set_one, &do_insert},
+  {'N', "next", "ID",
+   gettext_noop
+   ("specify ID of an updated version to be published in the future"
+    " (for namespace insertions only)"),
+   1, &GNUNET_GETOPT_set_string, &next_id},
+  {'p', "priority", "PRIORITY",
+   gettext_noop ("specify the priority of the content"),
+   1, &GNUNET_GETOPT_set_uint, &priority},
+  {'P', "pseudonym", "NAME",
+   gettext_noop
+   ("publish the files under the pseudonym NAME (place file into namespace)"),
+   1, &GNUNET_GETOPT_set_string, &pseudonym},
+  // *: option not yet used... (need FS API support!)
+  {'s', "simulate-only", NULL,
+   gettext_noop ("only simulate the process but do not do any "
+                 "actual publishing (useful to compute URIs)"),
+   0, &GNUNET_GETOPT_set_one, &do_simulate},
+  {'t', "this", "ID",
+   gettext_noop ("set the ID of this version of the publication"
+                 " (for namespace insertions only)"),
+   1, &GNUNET_GETOPT_set_string, &this_id},
+  // *: option not yet used... (need FS API support!)
+  {'u', "uri", "URI",
+   gettext_noop ("URI to be published (can be used instead of passing a "
+                 "file to add keywords to the file with the respective URI)"),
+   1, &GNUNET_GETOPT_set_string, &uri_string},
+  GNUNET_GETOPT_OPTION_END
+};
+
+
+/**
+ * The main function to publish content to GNUnet.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+  return (GNUNET_OK ==
+          GNUNET_PROGRAM_run (argc,
+                              argv,
+                              "gnunet-publish",
+                              gettext_noop
+                              ("Publish files on GNUnet."),
+                              options, &run, NULL)) ? ret : 1;
+}
+
+/* end of gnunet-publish.c */
+
+////////////////////////////////////////////////////////////////
+
+
+/**
+ * Print progess message.
+ */
+static void *
+printstatus (void *ctx, const GNUNET_FSUI_Event * event)
+{
+  unsigned long long delta;
+  char *fstring;
+
+  switch (event->type)
+    {
+    case GNUNET_FSUI_upload_progress:
+      if (*verboselevel)
+        {
+          char *ret;
+          GNUNET_CronTime now;
+
+          now = GNUNET_get_time ();
+          delta = event->data.UploadProgress.eta - now;
+          if (event->data.UploadProgress.eta < now)
+            delta = 0;
+          ret = GNUNET_get_time_interval_as_fancy_string (delta);
+          PRINTF (_("%16llu of %16llu bytes inserted "
+                    "(estimating %6s to completion) - %s\n"),
+                  event->data.UploadProgress.completed,
+                  event->data.UploadProgress.total,
+                  ret, event->data.UploadProgress.filename);
+          GNUNET_free (ret);
+        }
+      break;
+    case GNUNET_FSUI_upload_completed:
+      if (*verboselevel)
+        {
+          delta = GNUNET_get_time () - start_time;
+          PRINTF (_("Upload of `%s' complete, "
+                    "%llu bytes took %llu seconds (%8.3f KiB/s).\n"),
+                  event->data.UploadCompleted.filename,
+                  event->data.UploadCompleted.total,
+                  delta / GNUNET_CRON_SECONDS,
+                  (delta == 0)
+                  ? (double) (-1.0)
+                  : (double) (event->data.UploadCompleted.total
+                              / 1024.0 * GNUNET_CRON_SECONDS / delta));
+        }
+      fstring = GNUNET_ECRS_uri_to_string (event->data.UploadCompleted.uri);
+      printf (_("File `%s' has URI: %s\n"),
+              event->data.UploadCompleted.filename, fstring);
+      GNUNET_free (fstring);
+      if (ul == event->data.UploadCompleted.uc.pos)
+        {
+          postProcess (event->data.UploadCompleted.uri);
+          errorCode = 0;
+          GNUNET_shutdown_initiate ();
+        }
+      break;
+    case GNUNET_FSUI_upload_aborted:
+      printf (_("\nUpload aborted.\n"));
+      errorCode = 2;
+      GNUNET_shutdown_initiate ();
+      break;
+    case GNUNET_FSUI_upload_error:
+      printf (_("\nError uploading file: %s"),
+              event->data.UploadError.message);
+      errorCode = 3;
+      GNUNET_shutdown_initiate ();
+      break;
+    case GNUNET_FSUI_upload_started:
+    case GNUNET_FSUI_upload_stopped:
+      break;
+    default:
+      printf (_("\nUnexpected event: %d\n"), event->type);
+      GNUNET_GE_BREAK (ectx, 0);
+      break;
+    }
+  return NULL;
+}
+#endif
+
+/* end of gnunet-publish.c */

Modified: gnunet/src/include/gnunet_connection_lib.h
===================================================================
--- gnunet/src/include/gnunet_connection_lib.h  2009-08-27 11:14:19 UTC (rev 
8863)
+++ gnunet/src/include/gnunet_connection_lib.h  2009-08-28 09:05:15 UTC (rev 
8864)
@@ -23,8 +23,8 @@
  * @brief basic, low-level TCP networking interface
  * @author Christian Grothoff
  */
-#ifndef GNUNET_NETWORK_LIB_H
-#define GNUNET_NETWORK_LIB_H
+#ifndef GNUNET_CONNECTION_LIB_H
+#define GNUNET_CONNECTION_LIB_H
 
 #ifdef __cplusplus
 extern "C"
@@ -325,6 +325,6 @@
 #endif
 
 
-/* ifndef GNUNET_NETWORK_LIB_H */
+/* ifndef GNUNET_CONNECTION_LIB_H */
 #endif
 /* end of gnunet_connection_lib.h */

Modified: gnunet/src/include/gnunet_container_lib.h
===================================================================
--- gnunet/src/include/gnunet_container_lib.h   2009-08-27 11:14:19 UTC (rev 
8863)
+++ gnunet/src/include/gnunet_container_lib.h   2009-08-28 09:05:15 UTC (rev 
8864)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008 Christian Grothoff (and 
other contributing authors)
+     (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 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
@@ -201,11 +201,16 @@
 
 /**
  * Create a fresh MetaData token.
+ * 
+ * @return empty meta-data container
  */
 struct GNUNET_CONTAINER_MetaData *GNUNET_CONTAINER_meta_data_create (void);
 
 /**
  * Duplicate a MetaData token.
+ * 
+ * @param meta what to duplicate
+ * @return duplicate meta-data container
  */
 struct GNUNET_CONTAINER_MetaData *GNUNET_CONTAINER_meta_data_duplicate (const
                                                                         struct
@@ -214,12 +219,18 @@
 
 /**
  * Free meta data.
+ *
+ * @param md what to free
  */
 void GNUNET_CONTAINER_meta_data_destroy (struct GNUNET_CONTAINER_MetaData
                                          *md);
 
 /**
  * Test if two MDs are equal.
+ *
+ * @param md1 first value to check
+ * @param md2 other value to check
+ * @return GNUNET_YES if they are equal
  */
 int GNUNET_CONTAINER_meta_data_test_equal (const struct
                                            GNUNET_CONTAINER_MetaData *md1,
@@ -229,6 +240,10 @@
 
 /**
  * Extend metadata.
+ *
+ * @param md metadata to extend
+ * @param type type of the new entry
+ * @param data value for the entry
  * @return GNUNET_OK on success, GNUNET_SYSERR if this entry already exists
  */
 int GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md,
@@ -237,6 +252,10 @@
 
 /**
  * Remove an item.
+ *
+ * @param type type of the item to remove
+ * @param data specific value to remove, NULL to remove all
+ *        entries of the given type
  * @return GNUNET_OK on success, GNUNET_SYSERR if the item does not exist in md
  */
 int GNUNET_CONTAINER_meta_data_delete (struct GNUNET_CONTAINER_MetaData *md,
@@ -246,6 +265,8 @@
 /**
  * Add the current time as the publication date
  * to the meta-data.
+ *
+ * @param md metadata to modify
  */
 void GNUNET_CONTAINER_meta_data_add_publication_date (struct
                                                       GNUNET_CONTAINER_MetaData
@@ -254,6 +275,9 @@
 /**
  * Iterate over MD entries, excluding thumbnails.
  *
+ * @param md metadata to inspect
+ * @param iterator function to call on each entry
+ * @param closure closure for iterator
  * @return number of entries
  */
 int GNUNET_CONTAINER_meta_data_get_contents (const struct
@@ -263,6 +287,9 @@
 
 /**
  * Get the first MD entry of the given type.
+ *
+ * @param md metadata to inspect
+ * @param type type to look for
  * @return NULL if we do not have any such entry,
  *  otherwise client is responsible for freeing the value!
  */
@@ -272,7 +299,9 @@
 
 /**
  * Get the first matching MD entry of the given types.
- * @paarm ... -1-terminated list of types
+ *
+ * @param md metadata to inspect
+ * @param ... -1-terminated list of types
  * @return NULL if we do not have any such entry,
  *  otherwise client is responsible for freeing the value!
  */
@@ -283,6 +312,7 @@
 /**
  * Get a thumbnail from the meta-data (if present).
  *
+ * @param md metadata to inspect
  * @param thumb will be set to the thumbnail data.  Must be
  *        freed by the caller!
  * @return number of bytes in thumbnail, 0 if not available
@@ -294,6 +324,9 @@
 /**
  * Extract meta-data from a file.
  *
+ * @param md metadata to set
+ * @param filename name of file to inspect
+ * @param extractors plugins to use
  * @return GNUNET_SYSERR on error, otherwise the number
  *   of meta-data items obtained
  */
@@ -315,12 +348,13 @@
 /**
  * Serialize meta-data to target.
  *
+ * @param md metadata to serialize
  * @param size maximum number of bytes available
  * @param opt is it ok to just write SOME of the
  *        meta-data to match the size constraint,
  *        possibly discarding some data?
  * @return number of bytes written on success,
- *         GNUNET_SYSERR on error (typically: not enough
+ *         -1 on error (typically: not enough
  *         space)
  */
 ssize_t GNUNET_CONTAINER_meta_data_serialize (const struct
@@ -334,9 +368,12 @@
 /**
  * Compute size of the meta-data in
  * serialized form.
+ *
+ * @param md metadata to inspect
  * @param opt is it ok to just write SOME of the
  *        meta-data to match the size constraint,
  *        possibly discarding some data?
+ * @return number of bytes needed for serialization, -1 on error
  */
 ssize_t GNUNET_CONTAINER_meta_data_get_serialized_size (const struct
                                                        
GNUNET_CONTAINER_MetaData
@@ -347,6 +384,8 @@
 
 /**
  * Deserialize meta-data.  Initializes md.
+ *
+ * @param input serialized meta-data.
  * @param size number of bytes available
  * @return MD on success, NULL on error (i.e.
  *         bad format)
@@ -359,6 +398,7 @@
  * Does the meta-data claim that this is a directory?
  * Checks if the mime-type is that of a GNUnet directory.
  *
+ * @param md metadata to inspect
  * @return GNUNET_YES if it is, GNUNET_NO if it is not, GNUNET_SYSERR if
  *  we have no mime-type information (treat as 'GNUNET_NO')
  */

Modified: gnunet/src/include/gnunet_fs_service.h
===================================================================
--- gnunet/src/include/gnunet_fs_service.h      2009-08-27 11:14:19 UTC (rev 
8863)
+++ gnunet/src/include/gnunet_fs_service.h      2009-08-28 09:05:15 UTC (rev 
8864)
@@ -21,6 +21,10 @@
  * @file include/gnunet_fs_service.h
  * @brief API for file-sharing via GNUnet 
  * @author Christian Grothoff
+ *
+ * TODO:
+ * - extend API with support for publish simulation (-s)
+ *   and URI-argument binding to keyword/namespace (-u)
  */
 #ifndef GNUNET_FS_LIB_H
 #define GNUNET_FS_LIB_H
@@ -398,7 +402,7 @@
  * @return GNUNET_OK on success
  */
 int
-GNUNET_FS_getopt_configure_set_keywords (struct 
GNUNET_GETOPT_CommandLineProcessorContext* ctx, 
+GNUNET_FS_getopt_set_keywords (struct 
GNUNET_GETOPT_CommandLineProcessorContext* ctx, 
                                         void *scls,
                                         const char *option,
                                         const char *value);
@@ -417,7 +421,7 @@
  * @return GNUNET_OK on success
  */
 int
-GNUNET_FS_getopt_configure_set_metadata (struct 
GNUNET_GETOPT_CommandLineProcessorContext* ctx, 
+GNUNET_FS_getopt_set_metadata (struct 
GNUNET_GETOPT_CommandLineProcessorContext* ctx, 
                                         void *scls,
                                         const char *option,
                                         const char *value);

Modified: gnunet/src/include/gnunet_network_lib.h
===================================================================
--- gnunet/src/include/gnunet_network_lib.h     2009-08-27 11:14:19 UTC (rev 
8863)
+++ gnunet/src/include/gnunet_network_lib.h     2009-08-28 09:05:15 UTC (rev 
8864)
@@ -24,8 +24,8 @@
  * @author Nils Durner
  */
 
-#ifndef GNUNET_NETWORK_LIB_H_
-#define GNUNET_NETWORK_LIB_H_
+#ifndef GNUNET_NETWORK_LIB_H
+#define GNUNET_NETWORK_LIB_H
 
 #ifdef __cplusplus
 extern "C"
@@ -54,6 +54,11 @@
                       struct sockaddr *address,
                       socklen_t *address_len);
 
+int
+GNUNET_NETWORK_socket_set_inheritable (const struct GNUNET_NETWORK_Descriptor
+                                       *desc);
+
+
 int GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Descriptor *desc,
                     const struct sockaddr *address, socklen_t address_len);
 
@@ -128,7 +133,7 @@
 
 int GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1, 
const struct GNUNET_NETWORK_FDSet *fds2);
 
-struct GNUNET_NETWORK_FDSet *GNUNET_NETWORK_fdset_create ();
+struct GNUNET_NETWORK_FDSet *GNUNET_NETWORK_fdset_create (void);
 
 void GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds);
 
@@ -140,4 +145,4 @@
 }
 #endif
 
-#endif /* GNUNET_NETWORK_LIB_H_ */
+#endif /* GNUNET_NETWORK_LIB_H */

Modified: gnunet/src/util/Makefile.am
===================================================================
--- gnunet/src/util/Makefile.am 2009-08-27 11:14:19 UTC (rev 8863)
+++ gnunet/src/util/Makefile.am 2009-08-28 09:05:15 UTC (rev 8864)
@@ -37,6 +37,7 @@
   getopt.c \
   getopt_helpers.c \
   network.c \
+  network_socket.c \
   os_installation.c \
   os_load.c \
   os_network.c \
@@ -49,7 +50,6 @@
   server_tc.c \
   service.c \
   signal.c \
-  sock.c \
   strings.c \
   time.c \
   $(WINSRC)

Modified: gnunet/src/util/container_meta_data.c
===================================================================
--- gnunet/src/util/container_meta_data.c       2009-08-27 11:14:19 UTC (rev 
8863)
+++ gnunet/src/util/container_meta_data.c       2009-08-28 09:05:15 UTC (rev 
8864)
@@ -689,6 +689,10 @@
 
 /**
  * Test if two MDs are equal.
+ *
+ * @param md1 first value to check
+ * @param md2 other value to check
+ * @return GNUNET_YES if they are equal
  */
 int
 GNUNET_CONTAINER_meta_data_test_equal (const struct GNUNET_CONTAINER_MetaData

Copied: gnunet/src/util/network_socket.c (from rev 8862, gnunet/src/util/sock.c)
===================================================================
--- gnunet/src/util/network_socket.c                            (rev 0)
+++ gnunet/src/util/network_socket.c    2009-08-28 09:05:15 UTC (rev 8864)
@@ -0,0 +1,678 @@
+/*
+     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/sock.c
+ * @brief basic, low-level networking interface
+ * @author Nils Durner
+ */
+
+#include "platform.h"
+#include "gnunet_disk_lib.h"
+#include "disk.h"
+#include "gnunet_container_lib.h"
+
+#define DEBUG_SOCK GNUNET_NO
+
+struct GNUNET_NETWORK_Descriptor
+{
+  int fd;
+};
+
+struct GNUNET_NETWORK_FDSet
+{
+  /* socket descriptors */
+  int nsds;
+  fd_set sds;
+#ifdef WINDOWS
+  /* handles */
+  struct GNUNET_CONTAINER_Vector *handles;
+#endif
+};
+
+#ifndef FD_COPY
+#define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
+#endif
+
+struct GNUNET_NETWORK_Descriptor *
+GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Descriptor *desc,
+                              struct sockaddr *address,
+                              socklen_t * address_len)
+{
+  struct GNUNET_NETWORK_Descriptor *ret;
+
+  ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Descriptor));
+  ret->fd = accept (desc->fd, address, address_len);
+#ifdef MINGW
+  if (INVALID_SOCKET == ret->fd)
+    SetErrnoFromWinsockError (WSAGetLastError ());
+#endif
+  return ret;
+}
+
+int
+GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Descriptor *desc,
+                            const struct sockaddr *address,
+                            socklen_t address_len)
+{
+  int ret;
+
+  ret = bind (desc->fd, address, address_len);
+#ifdef MINGW
+  if (SOCKET_ERROR == ret)
+    SetErrnoFromWinsockError (WSAGetLastError ());
+#endif
+  return ret;
+}
+
+/**
+ * Set if a socket should use blocking or non-blocking IO.
+ *
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ */
+int
+GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Descriptor *fd,
+                                    int doBlock)
+{
+#if MINGW
+  u_long mode;
+  mode = !doBlock;
+  if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
+    {
+      SetErrnoFromWinsockError (WSAGetLastError ());
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
+      return GNUNET_SYSERR;
+    }
+  return GNUNET_OK;
+
+#else
+  /* not MINGW */
+  int flags = fcntl (fd->fd, F_GETFL);
+  if (flags == -1)
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl");
+      return GNUNET_SYSERR;
+    }
+  if (doBlock)
+    flags &= ~O_NONBLOCK;
+  else
+    flags |= O_NONBLOCK;
+  if (0 != fcntl (fd->fd, F_SETFL, flags))
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl");
+      return GNUNET_SYSERR;
+    }
+  return GNUNET_OK;
+#endif
+}
+
+int
+GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Descriptor *desc)
+{
+  int ret;
+#ifdef MINGW
+  ret = closesocket (desc->fd);
+  if (SOCKET_ERROR != ret)
+    GNUNET_free (desc);
+  else
+    SetErrnoFromWinsockError (WSAGetLastError ());
+#else
+  ret = close (desc->fd);
+  if (-1 == ret)
+    {
+      GNUNET_free (desc);
+    }
+#endif
+
+  return ret;
+}
+
+int
+GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Descriptor *desc,
+                               const struct sockaddr *address,
+                               socklen_t address_len)
+{
+  int ret;
+
+  ret = connect (desc->fd, address, address_len);
+#ifdef MINGW
+  if (SOCKET_ERROR == ret)
+    SetErrnoFromWinsockError (WSAGetLastError ());
+#endif
+  return ret;
+}
+
+int
+GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Descriptor *desc,
+                                  int level, int optname, void *optval,
+                                  socklen_t * optlen)
+{
+  int ret;
+
+  ret = getsockopt (desc->fd, level, optname, optval, optlen);
+#ifdef MINGW
+  if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
+    *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
+  else if (SOCKET_ERROR == ret)
+    SetErrnoFromWinsockError (WSAGetLastError ());
+#endif
+  return ret;
+}
+
+int
+GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Descriptor *desc,
+                              int backlog)
+{
+  int ret;
+
+  ret = listen (desc->fd, backlog);
+#ifdef MINGW
+  if (SOCKET_ERROR == ret)
+    SetErrnoFromWinsockError (WSAGetLastError ());
+#endif
+
+  return ret;
+}
+
+ssize_t
+GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Descriptor * desc,
+                            void *buffer, size_t length, int flags)
+{
+  int ret;
+
+  ret = recv (desc->fd, buffer, length, flags);
+#ifdef MINGW
+  if (SOCKET_ERROR == ret)
+    SetErrnoFromWinsockError (WSAGetLastError ());
+#endif
+
+  return ret;
+}
+
+ssize_t
+GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Descriptor * desc,
+                            const void *buffer, size_t length, int flags)
+{
+  int ret;
+
+  ret = send (desc->fd, buffer, length, flags);
+#ifdef MINGW
+  if (SOCKET_ERROR == ret)
+    SetErrnoFromWinsockError (WSAGetLastError ());
+#endif
+
+  return ret;
+}
+
+ssize_t
+GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Descriptor * desc,
+                              const void *message, size_t length, int flags,
+                              const struct sockaddr * dest_addr,
+                              socklen_t dest_len)
+{
+  int ret;
+
+  ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
+#ifdef MINGW
+  if (SOCKET_ERROR == ret)
+    SetErrnoFromWinsockError (WSAGetLastError ());
+#endif
+
+  return ret;
+}
+
+int
+GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Descriptor *fd,
+                                  int level, int option_name,
+                                  const void *option_value,
+                                  socklen_t option_len)
+{
+  int ret;
+
+  ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
+#ifdef MINGW
+  if (SOCKET_ERROR == ret)
+    SetErrnoFromWinsockError (WSAGetLastError ());
+#endif
+
+  return ret;
+}
+
+struct GNUNET_NETWORK_Descriptor *
+GNUNET_NETWORK_socket_socket (int domain, int type, int protocol)
+{
+  struct GNUNET_NETWORK_Descriptor *ret;
+
+  ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Descriptor));
+  ret->fd = socket (domain, type, protocol);
+#ifdef MINGW
+  if (INVALID_SOCKET == ret->fd)
+    SetErrnoFromWinsockError (WSAGetLastError ());
+#endif
+
+  if (ret->fd < 0)
+    {
+      GNUNET_free (ret);
+      ret = NULL;
+    }
+
+  return ret;
+}
+
+int
+GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Descriptor *desc,
+                                int how)
+{
+  int ret;
+
+  ret = shutdown (desc->fd, how);
+#ifdef MINGW
+  if (ret != 0)
+    SetErrnoFromWinsockError (WSAGetLastError ());
+#endif
+
+  return ret;
+}
+
+int
+GNUNET_NETWORK_socket_set_inheritable (const struct GNUNET_NETWORK_Descriptor
+                                       *desc)
+{
+#ifdef MINGW
+  errno = ENOSYS;
+  return GNUNET_SYSERR;
+#else
+  return fcntl (desc->fd, F_SETFD,
+                fcntl (desc->fd,
+                       F_GETFD) | FD_CLOEXEC) ==
+    0 ? GNUNET_OK : GNUNET_SYSERR;
+#endif
+}
+
+void
+GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
+{
+  FD_ZERO (&fds->sds);
+  fds->nsds = 0;
+#ifdef MINGW
+  if (fds->handles)
+    GNUNET_CONTAINER_vector_destroy (fds->handles);
+  fds->handles = GNUNET_CONTAINER_vector_create (2);
+#endif
+}
+
+void
+GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
+                          const struct GNUNET_NETWORK_Descriptor *desc)
+{
+  FD_SET (desc->fd, &fds->sds);
+
+  if (desc->fd + 1 > fds->nsds)
+    fds->nsds = desc->fd + 1;
+}
+
+int
+GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
+                            const struct GNUNET_NETWORK_Descriptor *desc)
+{
+  return FD_ISSET (desc->fd, &fds->sds);
+}
+
+void
+GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
+                          const struct GNUNET_NETWORK_FDSet *src)
+{
+  int nfds;
+
+  for (nfds = src->nsds; nfds > 0; nfds--)
+    if (FD_ISSET (nfds, &src->sds))
+      {
+        FD_SET (nfds, &dst->sds);
+        if (nfds + 1 > dst->nsds)
+          dst->nsds = nfds + 1;
+      }
+}
+
+void
+GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
+                           const struct GNUNET_NETWORK_FDSet *from)
+{
+  FD_COPY (&from->sds, &to->sds);
+  to->nsds = from->nsds;
+#ifdef MINGW
+  void *obj;
+
+  if (to->handles)
+    GNUNET_CONTAINER_vector_destroy (to->handles);
+  to->handles = GNUNET_CONTAINER_vector_create (2);
+  for (obj = GNUNET_CONTAINER_vector_get_first (from->handles); obj != NULL;
+       obj = GNUNET_CONTAINER_vector_get_next (from->handles))
+    {
+      GNUNET_CONTAINER_vector_insert_last (to->handles, obj);
+    }
+#endif
+}
+
+void
+GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
+                                  const fd_set * from, int nfds)
+{
+  FD_COPY (from, &to->sds);
+  to->nsds = nfds;
+}
+
+void
+GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
+                                 const struct GNUNET_DISK_FileHandle *h)
+{
+#ifdef MINGW
+  HANDLE hw;
+
+  GNUNET_internal_disk_file_handle (h, &hw, sizeof (HANDLE));
+  GNUNET_CONTAINER_vector_insert_last (fds->handles, h);
+#else
+  int fd;
+
+  GNUNET_internal_disk_file_handle (h, &fd, sizeof (int));
+  FD_SET (fd, &fds->sds);
+  if (fd + 1 > fds->nsds)
+    fds->nsds = fd + 1;
+#endif
+}
+
+int
+GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
+                                   const struct GNUNET_DISK_FileHandle *h)
+{
+#ifdef MINGW
+  return GNUNET_CONTAINER_vector_index_of (fds->handles, h->h) !=
+    (unsigned int) -1;
+#else
+  return FD_ISSET (h->fd, &fds->sds);
+#endif
+}
+
+int
+GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
+                              const struct GNUNET_NETWORK_FDSet *fds2)
+{
+  int nfds;
+
+  nfds = fds1->nsds;
+  if (nfds < fds2->nsds)
+    nfds = fds2->nsds;
+
+  for (; nfds >= 0; nfds--)
+    if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
+      return GNUNET_YES;
+
+  return GNUNET_NO;
+}
+
+struct GNUNET_NETWORK_FDSet *
+GNUNET_NETWORK_fdset_create ()
+{
+  struct GNUNET_NETWORK_FDSet *fds;
+
+  fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
+#ifdef MINGW
+  fds->handles = NULL;
+#endif
+  GNUNET_NETWORK_fdset_zero (fds);
+
+  return fds;
+}
+
+void
+GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
+{
+#ifdef MINGW
+  GNUNET_CONTAINER_vector_destroy (fds->handles);
+#endif
+  GNUNET_free (fds);
+}
+
+int
+GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
+                              struct GNUNET_NETWORK_FDSet *wfds,
+                              struct GNUNET_NETWORK_FDSet *efds,
+                              const struct GNUNET_TIME_Relative timeout)
+{
+  int nfds;
+
+  nfds = 0;
+
+  if (rfds)
+    nfds = rfds->nsds;
+  if (wfds && wfds->nsds > nfds)
+    nfds = wfds->nsds;
+  if (efds && efds->nsds > nfds)
+    nfds = efds->nsds;
+
+#ifndef MINGW
+  struct timeval tv;
+
+  tv.tv_sec = timeout.value / GNUNET_TIME_UNIT_SECONDS.value;
+  tv.tv_usec = (timeout.value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.value))
+    / GNUNET_TIME_UNIT_MILLISECONDS.value;
+
+  return select (nfds + 1, rfds ? &rfds->sds : NULL, wfds ? &wfds->sds : NULL,
+      efds ? &efds->sds : NULL, timeout.value
+          == GNUNET_TIME_UNIT_FOREVER_REL.value ? NULL : &tv);
+#else
+  DWORD limit;
+  fd_set sock_read, sock_write, sock_except;
+  fd_set aread, awrite, aexcept;
+  int i;
+  struct timeval tvslice;
+  int retcode;
+  DWORD ms_total;
+
+#define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
+
+  /* calculate how long we need to wait in milliseconds */
+  if (timeout.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
+    ms_total = INFINITE;
+  else
+    ms_total = timeout.value / GNUNET_TIME_UNIT_MILLISECONDS.value;
+
+  /* select() may be used as a portable way to sleep */
+  if (!(rfds || wfds || efds))
+    {
+      Sleep (ms_total);
+
+      return 0;
+    }
+
+  if (rfds)
+    sock_read = rfds->sds;
+  else
+    FD_ZERO(&sock_read);
+
+  if (wfds)
+    sock_write = wfds->sds;
+  else
+    FD_ZERO(&sock_write);
+
+  if (efds)
+    sock_except = efds->sds;
+  else
+    FD_ZERO(&sock_except);
+
+  /*
+  if (rfds)
+    FD_COPY (&rfds->sds, &sock_read);
+  else
+    FD_ZERO(&sock_read);
+
+  if (wfds)
+    FD_COPY (&wfds->sds, &sock_write);
+  else
+    FD_ZERO(&sock_write);
+
+  if (efds)
+    FD_COPY (&efds->sds, &sock_except);
+  else
+    FD_ZERO(&sock_except);
+*/
+
+  /* multiplex between winsock select() and waiting on the handles */
+
+  FD_ZERO (&aread);
+  FD_ZERO (&awrite);
+  FD_ZERO (&aexcept);
+
+  limit = GetTickCount () + ms_total;
+  do
+    {
+      retcode = 0;
+
+      if (nfds > 0)
+        {
+          /* overwrite the zero'd sets here; the select call
+           * will clear those that are not active */
+
+          FD_COPY (&sock_read, &aread);
+          FD_COPY (&sock_write, &awrite);
+          FD_COPY (&sock_except, &aexcept);
+
+          tvslice.tv_sec = 0;
+          tvslice.tv_usec = 100000;
+
+          if ((retcode =
+               select (nfds + 1, &aread, &awrite, &aexcept,
+                       &tvslice)) == SOCKET_ERROR)
+            {
+              SetErrnoFromWinsockError (WSAGetLastError ());
+              if (errno == ENOTSOCK)
+                errno = EBADF;
+
+#if DEBUG_SOCK
+            GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select");
+#endif
+
+              goto select_loop_end;
+            }
+        }
+
+      /* Poll read pipes */
+      if (rfds)
+        for (i = GNUNET_CONTAINER_vector_size (rfds->handles) - 1; i >= 0; i--)
+          {
+            DWORD dwBytes;
+
+            if (!PeekNamedPipe
+                (GNUNET_CONTAINER_vector_get_at (rfds->handles, i), NULL, 0,
+                 NULL, &dwBytes, NULL))
+              {
+                GNUNET_CONTAINER_vector_remove_at (rfds->handles, i);
+
+                retcode = -1;
+                SetErrnoFromWinError (GetLastError ());
+#if DEBUG_SOCK
+            GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "PeekNamedPipe");
+#endif
+               goto select_loop_end;
+              }
+            else if (dwBytes)
+              {
+                retcode++;
+              }
+            else
+              GNUNET_CONTAINER_vector_remove_at (rfds->handles, i);
+          }
+
+      /* Poll for faulty pipes */
+      if (efds)
+        for (i = GNUNET_CONTAINER_vector_size (efds->handles); i >= 0; i--)
+          {
+            DWORD dwBytes;
+
+            if (PeekNamedPipe
+                (GNUNET_CONTAINER_vector_get_at (rfds->handles, i), NULL, 0,
+                 NULL, &dwBytes, NULL))
+              {
+                GNUNET_CONTAINER_vector_remove_at (efds->handles, i);
+
+                retcode++;
+              }
+          }
+
+      /* FIXME */
+      if (wfds)
+        GNUNET_assert (GNUNET_CONTAINER_vector_size (wfds->handles) == 0);
+
+      /* Check for closed sockets */
+      for (i = 0; i < nfds; i++)
+        {
+          if (SAFE_FD_ISSET (i, &sock_read))
+            {
+              struct sockaddr addr;
+              int len;
+
+              if (getpeername (i, &addr, &len) == SOCKET_ERROR)
+                {
+                  int err, len;
+
+                  len = sizeof (err);
+                  if (getsockopt
+                      (i, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == 0
+                      && err == WSAENOTCONN)
+                    {
+                      if (!SAFE_FD_ISSET (i, &aread))
+                        {
+                          FD_SET (i, &aread);
+                          retcode++;
+                        }
+                    }
+                }
+            }
+        }
+
+    select_loop_end:;
+    }
+  while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit));
+
+  if (retcode != -1)
+    {
+      if (rfds)
+        {
+          GNUNET_NETWORK_fdset_zero (rfds);
+          GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
+        }
+
+      if (wfds)
+        {
+          GNUNET_NETWORK_fdset_zero (wfds);
+          GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
+        }
+
+      if (efds)
+        {
+          GNUNET_NETWORK_fdset_zero (efds);
+          GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
+        }
+    }
+
+  return retcode;
+#endif
+}
+
+/* end of sock.c */

Deleted: gnunet/src/util/sock.c
===================================================================
--- gnunet/src/util/sock.c      2009-08-27 11:14:19 UTC (rev 8863)
+++ gnunet/src/util/sock.c      2009-08-28 09:05:15 UTC (rev 8864)
@@ -1,678 +0,0 @@
-/*
-     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/sock.c
- * @brief basic, low-level networking interface
- * @author Nils Durner
- */
-
-#include "platform.h"
-#include "gnunet_disk_lib.h"
-#include "disk.h"
-#include "gnunet_container_lib.h"
-
-#define DEBUG_SOCK GNUNET_NO
-
-struct GNUNET_NETWORK_Descriptor
-{
-  int fd;
-};
-
-struct GNUNET_NETWORK_FDSet
-{
-  /* socket descriptors */
-  int nsds;
-  fd_set sds;
-#ifdef WINDOWS
-  /* handles */
-  struct GNUNET_CONTAINER_Vector *handles;
-#endif
-};
-
-#ifndef FD_COPY
-#define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
-#endif
-
-struct GNUNET_NETWORK_Descriptor *
-GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Descriptor *desc,
-                              struct sockaddr *address,
-                              socklen_t * address_len)
-{
-  struct GNUNET_NETWORK_Descriptor *ret;
-
-  ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Descriptor));
-  ret->fd = accept (desc->fd, address, address_len);
-#ifdef MINGW
-  if (INVALID_SOCKET == ret->fd)
-    SetErrnoFromWinsockError (WSAGetLastError ());
-#endif
-  return ret;
-}
-
-int
-GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Descriptor *desc,
-                            const struct sockaddr *address,
-                            socklen_t address_len)
-{
-  int ret;
-
-  ret = bind (desc->fd, address, address_len);
-#ifdef MINGW
-  if (SOCKET_ERROR == ret)
-    SetErrnoFromWinsockError (WSAGetLastError ());
-#endif
-  return ret;
-}
-
-/**
- * Set if a socket should use blocking or non-blocking IO.
- *
- * @return GNUNET_OK on success, GNUNET_SYSERR on error
- */
-int
-GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Descriptor *fd,
-                                    int doBlock)
-{
-#if MINGW
-  u_long mode;
-  mode = !doBlock;
-  if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
-    {
-      SetErrnoFromWinsockError (WSAGetLastError ());
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
-      return GNUNET_SYSERR;
-    }
-  return GNUNET_OK;
-
-#else
-  /* not MINGW */
-  int flags = fcntl (fd->fd, F_GETFL);
-  if (flags == -1)
-    {
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl");
-      return GNUNET_SYSERR;
-    }
-  if (doBlock)
-    flags &= ~O_NONBLOCK;
-  else
-    flags |= O_NONBLOCK;
-  if (0 != fcntl (fd->fd, F_SETFL, flags))
-    {
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl");
-      return GNUNET_SYSERR;
-    }
-  return GNUNET_OK;
-#endif
-}
-
-int
-GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Descriptor *desc)
-{
-  int ret;
-#ifdef MINGW
-  ret = closesocket (desc->fd);
-  if (SOCKET_ERROR != ret)
-    GNUNET_free (desc);
-  else
-    SetErrnoFromWinsockError (WSAGetLastError ());
-#else
-  ret = close (desc->fd);
-  if (-1 == ret)
-    {
-      GNUNET_free (desc);
-    }
-#endif
-
-  return ret;
-}
-
-int
-GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Descriptor *desc,
-                               const struct sockaddr *address,
-                               socklen_t address_len)
-{
-  int ret;
-
-  ret = connect (desc->fd, address, address_len);
-#ifdef MINGW
-  if (SOCKET_ERROR == ret)
-    SetErrnoFromWinsockError (WSAGetLastError ());
-#endif
-  return ret;
-}
-
-int
-GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Descriptor *desc,
-                                  int level, int optname, void *optval,
-                                  socklen_t * optlen)
-{
-  int ret;
-
-  ret = getsockopt (desc->fd, level, optname, optval, optlen);
-#ifdef MINGW
-  if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
-    *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
-  else if (SOCKET_ERROR == ret)
-    SetErrnoFromWinsockError (WSAGetLastError ());
-#endif
-  return ret;
-}
-
-int
-GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Descriptor *desc,
-                              int backlog)
-{
-  int ret;
-
-  ret = listen (desc->fd, backlog);
-#ifdef MINGW
-  if (SOCKET_ERROR == ret)
-    SetErrnoFromWinsockError (WSAGetLastError ());
-#endif
-
-  return ret;
-}
-
-ssize_t
-GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Descriptor * desc,
-                            void *buffer, size_t length, int flags)
-{
-  int ret;
-
-  ret = recv (desc->fd, buffer, length, flags);
-#ifdef MINGW
-  if (SOCKET_ERROR == ret)
-    SetErrnoFromWinsockError (WSAGetLastError ());
-#endif
-
-  return ret;
-}
-
-ssize_t
-GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Descriptor * desc,
-                            const void *buffer, size_t length, int flags)
-{
-  int ret;
-
-  ret = send (desc->fd, buffer, length, flags);
-#ifdef MINGW
-  if (SOCKET_ERROR == ret)
-    SetErrnoFromWinsockError (WSAGetLastError ());
-#endif
-
-  return ret;
-}
-
-ssize_t
-GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Descriptor * desc,
-                              const void *message, size_t length, int flags,
-                              const struct sockaddr * dest_addr,
-                              socklen_t dest_len)
-{
-  int ret;
-
-  ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
-#ifdef MINGW
-  if (SOCKET_ERROR == ret)
-    SetErrnoFromWinsockError (WSAGetLastError ());
-#endif
-
-  return ret;
-}
-
-int
-GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Descriptor *fd,
-                                  int level, int option_name,
-                                  const void *option_value,
-                                  socklen_t option_len)
-{
-  int ret;
-
-  ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
-#ifdef MINGW
-  if (SOCKET_ERROR == ret)
-    SetErrnoFromWinsockError (WSAGetLastError ());
-#endif
-
-  return ret;
-}
-
-struct GNUNET_NETWORK_Descriptor *
-GNUNET_NETWORK_socket_socket (int domain, int type, int protocol)
-{
-  struct GNUNET_NETWORK_Descriptor *ret;
-
-  ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Descriptor));
-  ret->fd = socket (domain, type, protocol);
-#ifdef MINGW
-  if (INVALID_SOCKET == ret->fd)
-    SetErrnoFromWinsockError (WSAGetLastError ());
-#endif
-
-  if (ret->fd < 0)
-    {
-      GNUNET_free (ret);
-      ret = NULL;
-    }
-
-  return ret;
-}
-
-int
-GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Descriptor *desc,
-                                int how)
-{
-  int ret;
-
-  ret = shutdown (desc->fd, how);
-#ifdef MINGW
-  if (ret != 0)
-    SetErrnoFromWinsockError (WSAGetLastError ());
-#endif
-
-  return ret;
-}
-
-int
-GNUNET_NETWORK_socket_set_inheritable (const struct GNUNET_NETWORK_Descriptor
-                                       *desc)
-{
-#ifdef MINGW
-  errno = ENOSYS;
-  return GNUNET_SYSERR;
-#else
-  return fcntl (desc->fd, F_SETFD,
-                fcntl (desc->fd,
-                       F_GETFD) | FD_CLOEXEC) ==
-    0 ? GNUNET_OK : GNUNET_SYSERR;
-#endif
-}
-
-void
-GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
-{
-  FD_ZERO (&fds->sds);
-  fds->nsds = 0;
-#ifdef MINGW
-  if (fds->handles)
-    GNUNET_CONTAINER_vector_destroy (fds->handles);
-  fds->handles = GNUNET_CONTAINER_vector_create (2);
-#endif
-}
-
-void
-GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
-                          const struct GNUNET_NETWORK_Descriptor *desc)
-{
-  FD_SET (desc->fd, &fds->sds);
-
-  if (desc->fd + 1 > fds->nsds)
-    fds->nsds = desc->fd + 1;
-}
-
-int
-GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
-                            const struct GNUNET_NETWORK_Descriptor *desc)
-{
-  return FD_ISSET (desc->fd, &fds->sds);
-}
-
-void
-GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
-                          const struct GNUNET_NETWORK_FDSet *src)
-{
-  int nfds;
-
-  for (nfds = src->nsds; nfds > 0; nfds--)
-    if (FD_ISSET (nfds, &src->sds))
-      {
-        FD_SET (nfds, &dst->sds);
-        if (nfds + 1 > dst->nsds)
-          dst->nsds = nfds + 1;
-      }
-}
-
-void
-GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
-                           const struct GNUNET_NETWORK_FDSet *from)
-{
-  FD_COPY (&from->sds, &to->sds);
-  to->nsds = from->nsds;
-#ifdef MINGW
-  void *obj;
-
-  if (to->handles)
-    GNUNET_CONTAINER_vector_destroy (to->handles);
-  to->handles = GNUNET_CONTAINER_vector_create (2);
-  for (obj = GNUNET_CONTAINER_vector_get_first (from->handles); obj != NULL;
-       obj = GNUNET_CONTAINER_vector_get_next (from->handles))
-    {
-      GNUNET_CONTAINER_vector_insert_last (to->handles, obj);
-    }
-#endif
-}
-
-void
-GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
-                                  const fd_set * from, int nfds)
-{
-  FD_COPY (from, &to->sds);
-  to->nsds = nfds;
-}
-
-void
-GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
-                                 const struct GNUNET_DISK_FileHandle *h)
-{
-#ifdef MINGW
-  HANDLE hw;
-
-  GNUNET_internal_disk_file_handle (h, &hw, sizeof (HANDLE));
-  GNUNET_CONTAINER_vector_insert_last (fds->handles, h);
-#else
-  int fd;
-
-  GNUNET_internal_disk_file_handle (h, &fd, sizeof (int));
-  FD_SET (fd, &fds->sds);
-  if (fd + 1 > fds->nsds)
-    fds->nsds = fd + 1;
-#endif
-}
-
-int
-GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
-                                   const struct GNUNET_DISK_FileHandle *h)
-{
-#ifdef MINGW
-  return GNUNET_CONTAINER_vector_index_of (fds->handles, h->h) !=
-    (unsigned int) -1;
-#else
-  return FD_ISSET (h->fd, &fds->sds);
-#endif
-}
-
-int
-GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
-                              const struct GNUNET_NETWORK_FDSet *fds2)
-{
-  int nfds;
-
-  nfds = fds1->nsds;
-  if (nfds < fds2->nsds)
-    nfds = fds2->nsds;
-
-  for (; nfds >= 0; nfds--)
-    if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
-      return GNUNET_YES;
-
-  return GNUNET_NO;
-}
-
-struct GNUNET_NETWORK_FDSet *
-GNUNET_NETWORK_fdset_create ()
-{
-  struct GNUNET_NETWORK_FDSet *fds;
-
-  fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
-#ifdef MINGW
-  fds->handles = NULL;
-#endif
-  GNUNET_NETWORK_fdset_zero (fds);
-
-  return fds;
-}
-
-void
-GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
-{
-#ifdef MINGW
-  GNUNET_CONTAINER_vector_destroy (fds->handles);
-#endif
-  GNUNET_free (fds);
-}
-
-int
-GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
-                              struct GNUNET_NETWORK_FDSet *wfds,
-                              struct GNUNET_NETWORK_FDSet *efds,
-                              const struct GNUNET_TIME_Relative timeout)
-{
-  int nfds;
-
-  nfds = 0;
-
-  if (rfds)
-    nfds = rfds->nsds;
-  if (wfds && wfds->nsds > nfds)
-    nfds = wfds->nsds;
-  if (efds && efds->nsds > nfds)
-    nfds = efds->nsds;
-
-#ifndef MINGW
-  struct timeval tv;
-
-  tv.tv_sec = timeout.value / GNUNET_TIME_UNIT_SECONDS.value;
-  tv.tv_usec = (timeout.value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.value))
-    / GNUNET_TIME_UNIT_MILLISECONDS.value;
-
-  return select (nfds + 1, rfds ? &rfds->sds : NULL, wfds ? &wfds->sds : NULL,
-      efds ? &efds->sds : NULL, timeout.value
-          == GNUNET_TIME_UNIT_FOREVER_REL.value ? NULL : &tv);
-#else
-  DWORD limit;
-  fd_set sock_read, sock_write, sock_except;
-  fd_set aread, awrite, aexcept;
-  int i;
-  struct timeval tvslice;
-  int retcode;
-  DWORD ms_total;
-
-#define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
-
-  /* calculate how long we need to wait in milliseconds */
-  if (timeout.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
-    ms_total = INFINITE;
-  else
-    ms_total = timeout.value / GNUNET_TIME_UNIT_MILLISECONDS.value;
-
-  /* select() may be used as a portable way to sleep */
-  if (!(rfds || wfds || efds))
-    {
-      Sleep (ms_total);
-
-      return 0;
-    }
-
-  if (rfds)
-    sock_read = rfds->sds;
-  else
-    FD_ZERO(&sock_read);
-
-  if (wfds)
-    sock_write = wfds->sds;
-  else
-    FD_ZERO(&sock_write);
-
-  if (efds)
-    sock_except = efds->sds;
-  else
-    FD_ZERO(&sock_except);
-
-  /*
-  if (rfds)
-    FD_COPY (&rfds->sds, &sock_read);
-  else
-    FD_ZERO(&sock_read);
-
-  if (wfds)
-    FD_COPY (&wfds->sds, &sock_write);
-  else
-    FD_ZERO(&sock_write);
-
-  if (efds)
-    FD_COPY (&efds->sds, &sock_except);
-  else
-    FD_ZERO(&sock_except);
-*/
-
-  /* multiplex between winsock select() and waiting on the handles */
-
-  FD_ZERO (&aread);
-  FD_ZERO (&awrite);
-  FD_ZERO (&aexcept);
-
-  limit = GetTickCount () + ms_total;
-  do
-    {
-      retcode = 0;
-
-      if (nfds > 0)
-        {
-          /* overwrite the zero'd sets here; the select call
-           * will clear those that are not active */
-
-          FD_COPY (&sock_read, &aread);
-          FD_COPY (&sock_write, &awrite);
-          FD_COPY (&sock_except, &aexcept);
-
-          tvslice.tv_sec = 0;
-          tvslice.tv_usec = 100000;
-
-          if ((retcode =
-               select (nfds + 1, &aread, &awrite, &aexcept,
-                       &tvslice)) == SOCKET_ERROR)
-            {
-              SetErrnoFromWinsockError (WSAGetLastError ());
-              if (errno == ENOTSOCK)
-                errno = EBADF;
-
-#if DEBUG_SOCK
-            GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select");
-#endif
-
-              goto select_loop_end;
-            }
-        }
-
-      /* Poll read pipes */
-      if (rfds)
-        for (i = GNUNET_CONTAINER_vector_size (rfds->handles) - 1; i >= 0; i--)
-          {
-            DWORD dwBytes;
-
-            if (!PeekNamedPipe
-                (GNUNET_CONTAINER_vector_get_at (rfds->handles, i), NULL, 0,
-                 NULL, &dwBytes, NULL))
-              {
-                GNUNET_CONTAINER_vector_remove_at (rfds->handles, i);
-
-                retcode = -1;
-                SetErrnoFromWinError (GetLastError ());
-#if DEBUG_SOCK
-            GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "PeekNamedPipe");
-#endif
-               goto select_loop_end;
-              }
-            else if (dwBytes)
-              {
-                retcode++;
-              }
-            else
-              GNUNET_CONTAINER_vector_remove_at (rfds->handles, i);
-          }
-
-      /* Poll for faulty pipes */
-      if (efds)
-        for (i = GNUNET_CONTAINER_vector_size (efds->handles); i >= 0; i--)
-          {
-            DWORD dwBytes;
-
-            if (PeekNamedPipe
-                (GNUNET_CONTAINER_vector_get_at (rfds->handles, i), NULL, 0,
-                 NULL, &dwBytes, NULL))
-              {
-                GNUNET_CONTAINER_vector_remove_at (efds->handles, i);
-
-                retcode++;
-              }
-          }
-
-      /* FIXME */
-      if (wfds)
-        GNUNET_assert (GNUNET_CONTAINER_vector_size (wfds->handles) == 0);
-
-      /* Check for closed sockets */
-      for (i = 0; i < nfds; i++)
-        {
-          if (SAFE_FD_ISSET (i, &sock_read))
-            {
-              struct sockaddr addr;
-              int len;
-
-              if (getpeername (i, &addr, &len) == SOCKET_ERROR)
-                {
-                  int err, len;
-
-                  len = sizeof (err);
-                  if (getsockopt
-                      (i, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == 0
-                      && err == WSAENOTCONN)
-                    {
-                      if (!SAFE_FD_ISSET (i, &aread))
-                        {
-                          FD_SET (i, &aread);
-                          retcode++;
-                        }
-                    }
-                }
-            }
-        }
-
-    select_loop_end:;
-    }
-  while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit));
-
-  if (retcode != -1)
-    {
-      if (rfds)
-        {
-          GNUNET_NETWORK_fdset_zero (rfds);
-          GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
-        }
-
-      if (wfds)
-        {
-          GNUNET_NETWORK_fdset_zero (wfds);
-          GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
-        }
-
-      if (efds)
-        {
-          GNUNET_NETWORK_fdset_zero (efds);
-          GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
-        }
-    }
-
-  return retcode;
-#endif
-}
-
-/* end of io.c */





reply via email to

[Prev in Thread] Current Thread [Next in Thread]