summaryrefslogtreecommitdiff
path: root/connect
diff options
context:
space:
mode:
Diffstat (limited to 'connect')
-rw-r--r--connect/ncbi_ansi_ext.h7
-rw-r--r--connect/ncbi_assert.h67
-rw-r--r--connect/ncbi_buffer.c104
-rw-r--r--connect/ncbi_buffer.h68
-rw-r--r--connect/ncbi_comm.h16
-rw-r--r--connect/ncbi_config.h20
-rw-r--r--connect/ncbi_connection.c91
-rw-r--r--connect/ncbi_connection.h7
-rw-r--r--connect/ncbi_connutil.c223
-rw-r--r--connect/ncbi_connutil.h90
-rw-r--r--connect/ncbi_core.c6
-rw-r--r--connect/ncbi_core.h32
-rw-r--r--connect/ncbi_core_c.c6
-rw-r--r--connect/ncbi_dispd.c56
-rw-r--r--connect/ncbi_file_connector.c6
-rw-r--r--connect/ncbi_ftp_connector.c718
-rw-r--r--connect/ncbi_ftp_connector.h84
-rw-r--r--connect/ncbi_heapmgr.c7
-rw-r--r--connect/ncbi_http_connector.c15
-rw-r--r--connect/ncbi_memory_connector.c35
-rw-r--r--connect/ncbi_memory_connector.h9
-rw-r--r--connect/ncbi_priv.h6
-rw-r--r--connect/ncbi_sendmail.c12
-rw-r--r--connect/ncbi_sendmail.h9
-rw-r--r--connect/ncbi_server_info.c6
-rw-r--r--connect/ncbi_service.c85
-rw-r--r--connect/ncbi_service.h20
-rw-r--r--connect/ncbi_servicep.h73
-rw-r--r--connect/ncbi_socket.c980
-rw-r--r--connect/ncbi_socket.h63
-rw-r--r--connect/ncbi_socket_connector.c6
-rw-r--r--connect/ncbi_socket_unix.h85
-rw-r--r--connect/ncbi_util.c6
-rw-r--r--connect/ncbibuf.c128
-rw-r--r--connect/ncbibuf.h149
-rw-r--r--connect/ncbisock.c535
-rw-r--r--connect/ncbisock.h412
-rw-r--r--connect/test/http_connector_hit.c16
-rw-r--r--connect/test/socket_io_bouncer.c6
-rw-r--r--connect/test/test_assert.h31
-rw-r--r--connect/test/test_ncbi_connutil_misc.c61
-rw-r--r--connect/test/test_ncbi_core.c6
-rw-r--r--connect/test/test_ncbi_dsock.c28
-rw-r--r--connect/test/test_ncbi_file_connector.c6
-rw-r--r--connect/test/test_ncbi_ftp_connector.c159
-rw-r--r--connect/test/test_ncbi_http_connector.c17
-rw-r--r--connect/test/test_ncbi_http_get.c42
-rwxr-xr-xconnect/test/test_ncbi_mac_mit_socket.c301
-rw-r--r--connect/test/test_ncbi_sendmail.c23
-rw-r--r--connect/test/test_ncbi_service_connector.c20
-rw-r--r--connect/test/test_ncbisock.c647
51 files changed, 2917 insertions, 2688 deletions
diff --git a/connect/ncbi_ansi_ext.h b/connect/ncbi_ansi_ext.h
index 4f4a60a9..82b985b4 100644
--- a/connect/ncbi_ansi_ext.h
+++ b/connect/ncbi_ansi_ext.h
@@ -1,7 +1,7 @@
#ifndef CONNECT___NCBI_ANSI_EXT__H
#define CONNECT___NCBI_ANSI_EXT__H
-/* $Id: ncbi_ansi_ext.h,v 6.12 2004/03/12 23:25:37 gorelenk Exp $
+/* $Id: ncbi_ansi_ext.h,v 6.13 2005/04/20 18:12:16 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -54,7 +54,7 @@ extern "C" {
* Return an identical malloc'ed string, which must be explicitly freed
* by free() when no longer needed.
*/
-extern char* strdup(const char* str);
+extern NCBI_XCONNECT_EXPORT char* strdup(const char* str);
#endif /*HAVE_STRDUP*/
@@ -120,6 +120,9 @@ extern NCBI_XCONNECT_EXPORT char* strncpy0(char* s1, const char* s2, size_t n);
/*
* --------------------------------------------------------------------------
* $Log: ncbi_ansi_ext.h,v $
+ * Revision 6.13 2005/04/20 18:12:16 lavr
+ * strdup() has got NCBI_XCONNECT_EXPORT
+ *
* Revision 6.12 2004/03/12 23:25:37 gorelenk
* Added export prefixes.
*
diff --git a/connect/ncbi_assert.h b/connect/ncbi_assert.h
new file mode 100644
index 00000000..5bf02e5d
--- /dev/null
+++ b/connect/ncbi_assert.h
@@ -0,0 +1,67 @@
+#ifndef CONNECT___NCBI_ASSERT__H
+#define CONNECT___NCBI_ASSERT__H
+
+/* $Id: ncbi_assert.h,v 1.1 2005/04/20 18:11:23 lavr Exp $
+ * ===========================================================================
+ *
+ * PUBLIC DOMAIN NOTICE
+ * National Center for Biotechnology Information
+ *
+ * This software/database is a "United States Government Work" under the
+ * terms of the United States Copyright Act. It was written as part of
+ * the author's official duties as a United States Government employee and
+ * thus cannot be copyrighted. This software/database is freely available
+ * to the public for use. The National Library of Medicine and the U.S.
+ * Government have not placed any restriction on its use or reproduction.
+ *
+ * Although all reasonable efforts have been taken to ensure the accuracy
+ * and reliability of the software and data, the NLM and the U.S.
+ * Government do not and cannot warrant the performance or results that
+ * may be obtained by using this software or data. The NLM and the U.S.
+ * Government disclaim all warranties, express or implied, including
+ * warranties of performance, merchantability or fitness for any particular
+ * purpose.
+ *
+ * Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author: Anton Lavrentiev
+ *
+ * File Description:
+ * Run-time debugging
+ */
+
+#include "ncbi_config.h"
+
+#if defined(verify)
+#undef verify
+#endif
+
+#if !defined(NDEBUG) && !defined(_DEBUG)
+# define NDEBUG
+#endif
+#include <assert.h>
+#if defined(NDEBUG)
+# define verify(expr) (void)(expr)
+#else
+# ifdef NCBI_COMPILER_METROWERKS
+ /* The following 2 headers are only required for Codewarrior
+ * on Mac to prototype printf() and abort() respectively */
+# include <stdio.h>
+# include <stdlib.h>
+# endif
+# define verify(expr) assert(expr)
+#endif
+
+
+/*
+ * --------------------------------------------------------------------------
+ * $Log: ncbi_assert.h,v $
+ * Revision 1.1 2005/04/20 18:11:23 lavr
+ * Initial revision
+ *
+ * ==========================================================================
+ */
+
+#endif /* CONNECT___NCBI_ASSERT__H */
diff --git a/connect/ncbi_buffer.c b/connect/ncbi_buffer.c
index 404f97c1..4807ffd3 100644
--- a/connect/ncbi_buffer.c
+++ b/connect/ncbi_buffer.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_buffer.c,v 6.13 2003/12/05 17:31:04 ucko Exp $
+/* $Id: ncbi_buffer.c,v 6.16 2004/11/17 20:44:32 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -51,7 +51,7 @@ typedef struct SBufChunkTag {
size_t size; /* of data (including the discarded "n_skip" bytes) */
size_t alloc_size; /* maximum available (allocated) size of "data" */
size_t n_skip; /* # of bytes already discarded(read) from the chunk */
- char data[1]; /* data stored in this chunk */
+ char* data; /* data stored in this chunk */
} SBufChunk;
@@ -98,12 +98,12 @@ extern size_t BUF_Size(BUF buf)
/* Create a new chunk.
* Allocate at least "chunk_size" bytes, but no less than "size" bytes.
+ * Special case: "size" == 0 results in no data storage allocation.
*/
static SBufChunk* s_AllocChunk(size_t size, size_t chunk_size)
{
size_t alloc_size = ((size + chunk_size - 1) / chunk_size) * chunk_size;
- SBufChunk* pChunk = (SBufChunk*)
- malloc((size_t) (&(((SBufChunk*)0)->data)) + alloc_size);
+ SBufChunk* pChunk = (SBufChunk*) malloc(sizeof(*pChunk) + alloc_size);
if ( !pChunk )
return 0;
@@ -111,19 +111,74 @@ static SBufChunk* s_AllocChunk(size_t size, size_t chunk_size)
pChunk->size = 0;
pChunk->alloc_size = alloc_size;
pChunk->n_skip = 0;
+ pChunk->data = alloc_size ? (char*) pChunk + sizeof(*pChunk) : 0;
return pChunk;
}
+extern int/*bool*/ BUF_Append(BUF* pBuf, const void* data, size_t size)
+{
+ SBufChunk* pChunk;
+ if ( !size )
+ return 1/*true*/;
+
+ /* init the buffer internals, if not init'd yet */
+ if (!*pBuf && !BUF_SetChunkSize(pBuf, 0))
+ return 0/*false*/;
+
+ pChunk = s_AllocChunk(0, (*pBuf)->chunk_size);
+ if ( !pChunk )
+ return 0/*false*/;
+
+ assert( !pChunk->data );
+ pChunk->alloc_size = size;
+ pChunk->size = size;
+ pChunk->data = (char*) data;
+
+ if ( (*pBuf)->last )
+ (*pBuf)->last->next = pChunk;
+ else
+ (*pBuf)->list = pChunk;
+ (*pBuf)->last = pChunk;
+ return 1/*true*/;
+}
+
+
+extern int/*bool*/ BUF_Prepend(BUF* pBuf, const void* data, size_t size)
+{
+ SBufChunk* pChunk;
+ if ( !size )
+ return 1/*true*/;
+
+ /* init the buffer internals, if not init'd yet */
+ if (!*pBuf && !BUF_SetChunkSize(pBuf, 0))
+ return 0/*false*/;
+
+ pChunk = s_AllocChunk(0, (*pBuf)->chunk_size);
+ if ( !pChunk )
+ return 0/*false*/;
+
+ assert( !pChunk->data );
+ pChunk->alloc_size = size;
+ pChunk->size = size;
+ pChunk->data = (char*) data;
+
+ if ( (*pBuf)->list )
+ pChunk->next = (*pBuf)->list;
+ (*pBuf)->list = pChunk;
+ return 1/*true*/;
+}
+
+
extern int/*bool*/ BUF_Write(BUF* pBuf, const void* data, size_t size)
{
- SBufChunk *pChunk, *pTail;
+ SBufChunk* pChunk, *pTail;
if ( !size )
- return 1 /* true */;
+ return 1/*true*/;
/* init the buffer internals, if not init'd yet */
- if (!*pBuf && !BUF_SetChunkSize(pBuf, 0) )
- return 0 /* false */;
+ if (!*pBuf && !BUF_SetChunkSize(pBuf, 0))
+ return 0/*false*/;
/* find the last allocated chunk */
pTail = (*pBuf)->last;
@@ -143,7 +198,7 @@ extern int/*bool*/ BUF_Write(BUF* pBuf, const void* data, size_t size)
if ( size ) {
pChunk = s_AllocChunk(size, (*pBuf)->chunk_size);
if ( !pChunk )
- return 0 /* false */;
+ return 0/*false*/;
pChunk->n_skip = 0;
pChunk->size = size;
memcpy(pChunk->data, data, size);
@@ -155,7 +210,7 @@ extern int/*bool*/ BUF_Write(BUF* pBuf, const void* data, size_t size)
(*pBuf)->list = pChunk;
(*pBuf)->last = pChunk;
}
- return 1 /* true */;
+ return 1/*true*/;
}
@@ -163,11 +218,11 @@ extern int/*bool*/ BUF_PushBack(BUF* pBuf, const void* data, size_t size)
{
SBufChunk* pChunk;
if ( !size )
- return 1 /* true */;
+ return 1/*true*/;
/* init the buffer internals, if not init'd yet */
if (!*pBuf && !BUF_SetChunkSize(pBuf, 0) )
- return 0 /* false */;
+ return 0/*false*/;
pChunk = (*pBuf)->list;
@@ -175,7 +230,7 @@ extern int/*bool*/ BUF_PushBack(BUF* pBuf, const void* data, size_t size)
if (!pChunk || size > pChunk->n_skip) {
pChunk = s_AllocChunk(size, (*pBuf)->chunk_size);
if ( !pChunk )
- return 0 /* false */;
+ return 0/*false*/;
pChunk->n_skip = pChunk->size = pChunk->alloc_size;
pChunk->next = (*pBuf)->list;
(*pBuf)->list = pChunk;
@@ -188,7 +243,7 @@ extern int/*bool*/ BUF_PushBack(BUF* pBuf, const void* data, size_t size)
assert(pChunk->n_skip >= size);
pChunk->n_skip -= size;
memcpy(pChunk->data + pChunk->n_skip, data, size);
- return 1 /* true */;
+ return 1/*true*/;
}
@@ -278,7 +333,7 @@ extern size_t BUF_Read(BUF buf, void* data, size_t size)
}
-extern void BUF_Destroy(BUF buf)
+extern void BUF_Erase(BUF buf)
{
if ( !buf )
return;
@@ -288,14 +343,31 @@ extern void BUF_Destroy(BUF buf)
buf->list = pChunk->next;
free(pChunk);
}
+ buf->last = 0;
+}
+
- free(buf);
+extern void BUF_Destroy(BUF buf)
+{
+ if (buf) {
+ BUF_Erase(buf);
+ free(buf);
+ }
}
/*
* ---------------------------------------------------------------------------
* $Log: ncbi_buffer.c,v $
+ * Revision 6.16 2004/11/17 20:44:32 lavr
+ * Slight source code formatting change
+ *
+ * Revision 6.15 2004/10/27 18:43:50 lavr
+ * +BUF_Erase()
+ *
+ * Revision 6.14 2004/10/27 18:09:58 lavr
+ * +BUF_Prepend(), +BUF_Append()
+ *
* Revision 6.13 2003/12/05 17:31:04 ucko
* Add a tail pointer to BUF_struct to avoid having to walk the entire
* list in BUF_Write.
diff --git a/connect/ncbi_buffer.h b/connect/ncbi_buffer.h
index ae85ff77..3b2acf53 100644
--- a/connect/ncbi_buffer.h
+++ b/connect/ncbi_buffer.h
@@ -1,7 +1,7 @@
#ifndef CONNECT___NCBI_BUFFER__H
#define CONNECT___NCBI_BUFFER__H
-/* $Id: ncbi_buffer.h,v 6.9 2003/04/10 12:52:15 siyan Exp $
+/* $Id: ncbi_buffer.h,v 6.11 2004/10/27 18:43:45 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -36,6 +36,8 @@
* Functions:
* BUF_SetChunkSize
* BUF_Size
+ * BUF_Prepend
+ * BUF_Append
* BUF_Write
* BUF_PushBack
* BUF_Peek
@@ -68,7 +70,8 @@ struct BUF_tag;
typedef struct BUF_tag* BUF; /* handle of a buffer */
-/* Set minimal size of a buffer memory chunk.
+/*!
+ * Set minimal size of a buffer memory chunk.
* Return the actually set chunk size on success; zero on error
* NOTE: if "*pBuf" == NULL then create it
* if "chunk_size" is passed 0 then set it to BUF_DEF_CHUNK_SIZE
@@ -80,13 +83,43 @@ extern NCBI_XCONNECT_EXPORT size_t BUF_SetChunkSize
);
-/* Return the number of bytes stored in "buf".
+/*!
+ * Return the number of bytes stored in "buf".
* NOTE: return 0 if "buf" == NULL
*/
extern NCBI_XCONNECT_EXPORT size_t BUF_Size(BUF buf);
-/* Add new data to the end of "*pBuf" (to be read last).
+/*!
+ * Prepend a block of data (of the specified size) to the
+ * beginning of the buffer (to be read first). Note that unlike
+ * BUF_Pushback(), in this call the data is not copied into the buffer
+ * but instead is just linked in from the original location.
+ * Return non-zero (true) if succeeded, zero (false) if failed.
+ */
+extern NCBI_XCONNECT_EXPORT int/*bool*/ BUF_Prepend
+(BUF* pBuf,
+ const void* data,
+ size_t size
+);
+
+
+/*!
+ * Append a block of data (of the specified size) past the end
+ * of the buffer (to be read last). Note that unlike
+ * BUF_Write(), in this call the data is not copied to the buffer
+ * but instead is just linked in from the original location.
+ * Return non-zero (true) if succeeded, zero (false) if failed.
+ */
+extern NCBI_XCONNECT_EXPORT int/*bool*/ BUF_Append
+(BUF* pBuf,
+ const void* data,
+ size_t size
+ );
+
+
+/*!
+ * Add new data to the end of "*pBuf" (to be read last).
* On error (failed memory allocation), return zero value.
* NOTE: if "*pBuf" == NULL then create it.
*/
@@ -97,7 +130,8 @@ extern NCBI_XCONNECT_EXPORT /*bool*/int BUF_Write
);
-/* Write the data to the very beginning of "*pBuf" (to be read first).
+/*!
+ * Write the data to the very beginning of "*pBuf" (to be read first).
* On error (failed memory allocation), return zero value.
* NOTE: if "*pBuf" == NULL then create it.
*/
@@ -108,7 +142,8 @@ extern NCBI_XCONNECT_EXPORT /*bool*/int BUF_PushBack
);
-/* Equivalent to "BUF_PeekAt(buf, 0, data, size)", see description below.
+/*!
+ * Equivalent to "BUF_PeekAt(buf, 0, data, size)", see description below.
*/
extern NCBI_XCONNECT_EXPORT size_t BUF_Peek
(BUF buf,
@@ -117,7 +152,8 @@ extern NCBI_XCONNECT_EXPORT size_t BUF_Peek
);
-/* Copy up to "size" bytes stored in "buf" (starting at position "pos")
+/*!
+ * Copy up to "size" bytes stored in "buf" (starting at position "pos")
* to "data".
* Return the # of copied bytes (can be less than "size").
* Return zero and do nothing if "buf" is NULL or "pos" >= BUF_Size(buf).
@@ -131,7 +167,8 @@ extern NCBI_XCONNECT_EXPORT size_t BUF_PeekAt
);
-/* Copy up to "size" bytes stored in "buf" to "data" and remove
+/*!
+ * Copy up to "size" bytes stored in "buf" to "data" and remove
* copied data from the "buf".
* Return the # of copied-and/or-removed bytes(can be less than "size")
* NOTE: if "buf" == NULL then do nothing and return 0
@@ -144,7 +181,14 @@ extern NCBI_XCONNECT_EXPORT size_t BUF_Read
);
-/* Destroy all internal data.
+/*!
+ * Make the buffer empty.
+ */
+extern NCBI_XCONNECT_EXPORT void BUF_Erase(BUF buf);
+
+
+/*!
+ * Destroy all internal data.
* NOTE: do nothing if "buf" == NULL
*/
extern NCBI_XCONNECT_EXPORT void BUF_Destroy(BUF buf);
@@ -161,6 +205,12 @@ extern NCBI_XCONNECT_EXPORT void BUF_Destroy(BUF buf);
/*
* ---------------------------------------------------------------------------
* $Log: ncbi_buffer.h,v $
+ * Revision 6.11 2004/10/27 18:43:45 lavr
+ * +BUF_Erase()
+ *
+ * Revision 6.10 2004/10/27 18:09:57 lavr
+ * +BUF_Prepend(), +BUF_Append()
+ *
* Revision 6.9 2003/04/10 12:52:15 siyan
* Changed group name for doxygen
*
diff --git a/connect/ncbi_comm.h b/connect/ncbi_comm.h
index 95254e1b..fde68503 100644
--- a/connect/ncbi_comm.h
+++ b/connect/ncbi_comm.h
@@ -1,7 +1,7 @@
#ifndef CONNECT___NCBI_COMM__H
#define CONNECT___NCBI_COMM__H
-/* $Id: ncbi_comm.h,v 6.9 2004/08/02 16:52:42 lavr Exp $
+/* $Id: ncbi_comm.h,v 6.10 2005/04/20 18:13:10 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -35,11 +35,6 @@
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
#define NCBID_WEBPATH "/Service/ncbid.cgi"
#define HTTP_CONNECTION_INFO "Connection-Info:"
#define HTTP_DISP_FAILURES "Dispatcher-Failures:"
@@ -49,6 +44,12 @@ extern "C" {
#define DISP_PROTOCOL_VERSION "1.0"
#define DISPD_MESSAGE_FILE ".dispd.msg"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
typedef unsigned int ticket_t;
@@ -60,6 +61,9 @@ typedef unsigned int ticket_t;
/*
* --------------------------------------------------------------------------
* $Log: ncbi_comm.h,v $
+ * Revision 6.10 2005/04/20 18:13:10 lavr
+ * extern "C" limited to code only (not preprocessor macros)
+ *
* Revision 6.9 2004/08/02 16:52:42 lavr
* +DISPD_MESSAGE_FILE
*
diff --git a/connect/ncbi_config.h b/connect/ncbi_config.h
index c24b641a..0c857916 100644
--- a/connect/ncbi_config.h
+++ b/connect/ncbi_config.h
@@ -1,7 +1,7 @@
#ifndef CONNECT___NCBI_CONFIG__H
#define CONNECT___NCBI_CONFIG__H
-/* $Id: ncbi_config.h,v 6.7 2003/04/02 16:20:53 rsmith Exp $
+/* $Id: ncbi_config.h,v 6.8 2004/10/19 19:33:51 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -37,21 +37,28 @@
*/
#include <ncbilcl.h>
+#ifdef NCBI_COMPILER_MW_MSL
+# undef NCBI_COMPILER_MW_MSL
+#endif
+
#if defined(OS_UNIX)
# define NCBI_OS_UNIX 1
# ifdef OS_UNIX_IRIX
-# define NCBI_OS_IRIX
+# define NCBI_OS_IRIX
# endif
# ifdef OS_UNIX_SOL
-# define NCBI_OS_SOLARIS
+# define NCBI_OS_SOLARIS
# endif
# ifdef OS_UNIX_BEOS
-# define NCBI_OS_BEOS
+# define NCBI_OS_BEOS
# endif
# ifdef OS_UNIX_DARWIN
-# define NCBI_OS_DARWIN 1
+# define NCBI_OS_DARWIN 1
# ifdef COMP_METRO
# define NCBI_COMPILER_METROWERKS 1
+# if _MSL_USING_MW_C_HEADERS
+# define NCBI_COMPILER_MW_MSL
+# endif
# endif
# endif
# if !defined(HAVE_GETHOSTBYNAME_R)
@@ -65,6 +72,9 @@
# endif
#elif defined(OS_MSWIN)
# define NCBI_OS_MSWIN 1
+# ifdef COMP_METRO
+# define NCBI_COMPILER_METROWERKS 1
+# endif
#elif defined(OS_MAC)
# define NCBI_OS_MAC 1
#endif
diff --git a/connect/ncbi_connection.c b/connect/ncbi_connection.c
index 5ef03d7c..3c8e405e 100644
--- a/connect/ncbi_connection.c
+++ b/connect/ncbi_connection.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_connection.c,v 6.42 2004/05/26 16:00:06 lavr Exp $
+/* $Id: ncbi_connection.c,v 6.44 2004/11/15 19:33:42 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -454,7 +454,7 @@ extern EIO_Status CONN_Write
if (!n_written)
return eIO_InvalidArg;
*n_written = 0;
- if (size && !buf)
+ if (size && !buf)
return eIO_InvalidArg;
CONN_NOT_NULL(Write);
@@ -540,11 +540,13 @@ static EIO_Status s_CONN_Read
}
/* read data from the internal peek buffer, if any */
- *n_read = peek
- ? BUF_Peek(conn->buf, buf, size) : BUF_Read(conn->buf, buf, size);
- if (*n_read == size)
- return eIO_Success;
- buf = (char*) buf + *n_read;
+ if ( size ) {
+ *n_read = peek
+ ? BUF_Peek(conn->buf, buf, size) : BUF_Read(conn->buf, buf, size);
+ if (*n_read == size)
+ return eIO_Success;
+ buf = (char*) buf + *n_read;
+ }
/* read data from the connection */
{{
@@ -554,7 +556,7 @@ static EIO_Status s_CONN_Read
conn->r_timeout == kDefaultTimeout ?
conn->meta.default_timeout : conn->r_timeout);
*n_read += x_read;
- if (peek && x_read) /* save data in the internal peek buffer */
+ if ( peek ) /* save data in the internal peek buffer */
verify(BUF_Write(&conn->buf, buf, x_read));
}}
@@ -615,7 +617,7 @@ extern EIO_Status CONN_Read
if (!n_read)
return eIO_InvalidArg;
*n_read = 0;
- if (size && !buf)
+ if (size && !buf)
return eIO_InvalidArg;
CONN_NOT_NULL(Read);
@@ -657,63 +659,62 @@ extern EIO_Status CONN_ReadLine
size_t* n_read
)
{
- EIO_Status status = eIO_Success;
- char w[1024];
- size_t len;
+ EIO_Status status = eIO_Success;
+ int/*bool*/ done = 0/*false*/;
+ size_t len;
if (!n_read)
return eIO_InvalidArg;
*n_read = 0;
- if (size && !line)
+ if (size && !line)
return eIO_InvalidArg;
CONN_NOT_NULL(ReadLine);
/* perform open, if not opened yet */
- if (conn->state != eCONN_Open && (status = s_Open(conn)) != eIO_Success)
- return status;
- assert(conn->state == eCONN_Open && conn->meta.list != 0);
+ if (conn->state != eCONN_Open)
+ status = s_Open(conn);
- /* flush the unwritten output data (if any) */
- if ( conn->meta.flush ) {
- conn->meta.flush(conn->meta.c_flush,
- conn->r_timeout == kDefaultTimeout ?
- conn->meta.default_timeout : conn->r_timeout);
+ if (status == eIO_Success) {
+ assert(conn->state == eCONN_Open && conn->meta.list != 0);
+ /* flush the unwritten output data (if any) */
+ if ( conn->meta.flush ) {
+ conn->meta.flush(conn->meta.c_flush,
+ conn->r_timeout == kDefaultTimeout ?
+ conn->meta.default_timeout : conn->r_timeout);
+ }
}
len = 0;
- while (len < size) {
+ while (status == eIO_Success) {
size_t i;
+ char w[1024];
size_t x_read = 0;
size_t x_size = BUF_Size(conn->buf);
- char* buf = size - len < sizeof(w) ? w : &line[len];
- if (x_size == 0 || x_size > sizeof(w))
+ char* x_buf = size - len < sizeof(w) ? w : line + len;
+ if (x_size == 0 || x_size > sizeof(w))
x_size = sizeof(w);
- status = s_CONN_Read(conn, buf, x_size, &x_read, 0);
- for (i = 0; i < x_read; i++) {
- if (buf == w)
- line[len] = buf[i];
- if (buf[i] == '\n') {
- line[len] = '\0';
- i++;
- break;
- } else if (++len >= size) {
+ status = s_CONN_Read(conn, x_buf, size ? x_size : 0, &x_read, 0);
+ for (i = 0; i < x_read && len < size; i++) {
+ char c = x_buf[i];
+ if (c == '\n') {
+ done = 1/*true*/;
i++;
break;
}
+ if (x_buf == w)
+ line[len] = c;
+ len++;
}
- if (i < x_read) {
- if (!BUF_PushBack(&conn->buf, &buf[i], x_read - i))
- status = eIO_Unknown;
+ if (i < x_read && !BUF_PushBack(&conn->buf, x_buf + i, x_read - i))
+ status = eIO_Unknown;
+ if (done || len >= size)
break;
- } else if (status != eIO_Success) {
- if (len < size)
- line[len] = '\0';
- break;
- }
}
-
+ if (len < size)
+ line[len] = '\0';
*n_read = len;
+
return status;
}
@@ -854,6 +855,12 @@ extern EIO_Status CONN_WaitAsync
/*
* --------------------------------------------------------------------------
* $Log: ncbi_connection.c,v $
+ * Revision 6.44 2004/11/15 19:33:42 lavr
+ * Speed-up CONN_ReadLine()
+ *
+ * Revision 6.43 2004/11/15 17:39:26 lavr
+ * Fix CONN_ReadLine() to always perform connector's read method
+ *
* Revision 6.42 2004/05/26 16:00:06 lavr
* Minor status fixes in CONN_SetTimeout() and CONN_ReadLine()
*
diff --git a/connect/ncbi_connection.h b/connect/ncbi_connection.h
index 20a6ca94..1881bcc2 100644
--- a/connect/ncbi_connection.h
+++ b/connect/ncbi_connection.h
@@ -1,7 +1,7 @@
#ifndef CONNECT___NCBI_CONNECTION__H
#define CONNECT___NCBI_CONNECTION__H
-/* $Id: ncbi_connection.h,v 6.20 2004/06/09 14:03:06 jcherry Exp $
+/* $Id: ncbi_connection.h,v 6.21 2004/10/26 14:47:42 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -194,7 +194,7 @@ extern NCBI_XCONNECT_EXPORT EIO_Status CONN_PushBack
* So does CONN_Close() but only if connection is was open before.
*/
extern NCBI_XCONNECT_EXPORT EIO_Status CONN_Flush
-(CONN conn /* [in] connection handle */
+(CONN conn /* [in] connection handle */
);
@@ -326,6 +326,9 @@ extern EIO_Status CONN_WaitAsync
/*
* ---------------------------------------------------------------------------
* $Log: ncbi_connection.h,v $
+ * Revision 6.21 2004/10/26 14:47:42 lavr
+ * Slight formatting
+ *
* Revision 6.20 2004/06/09 14:03:06 jcherry
* Moved #define out of enum body (SWIG was choking on this)
*
diff --git a/connect/ncbi_connutil.c b/connect/ncbi_connutil.c
index e127bfcb..4091611d 100644
--- a/connect/ncbi_connutil.c
+++ b/connect/ncbi_connutil.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_connutil.c,v 6.65 2004/10/14 13:51:42 lavr Exp $
+/* $Id: ncbi_connutil.c,v 6.72 2005/04/20 15:50:30 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -43,7 +43,7 @@ static const char* s_GetValue(const char* service, const char* param,
char* value, size_t value_size,
const char* def_value)
{
- char key[250];
+ char key[256];
char* sec;
const char* val;
@@ -105,7 +105,7 @@ extern SConnNetInfo* ConnNetInfo_Create(const char* service)
(service && *service
? strlen(service) + 1 : 0));
/* aux. storage for the string-to-int conversions, etc. */
- char str[32];
+ char str[256];
int val;
double dbl;
char* s;
@@ -146,8 +146,7 @@ extern SConnNetInfo* ConnNetInfo_Create(const char* service)
info->timeout = 0;
} else {
info->timeout = &info->tmo;
- dbl = atof(str);
- if (dbl <= 0.0)
+ if (!*str || (dbl = atof(str)) < 0.0)
dbl = DEF_CONN_TIMEOUT;
info->timeout->sec = (unsigned int) dbl;
info->timeout->usec = (unsigned int)
@@ -210,8 +209,19 @@ extern SConnNetInfo* ConnNetInfo_Create(const char* service)
strcasecmp(str, "true") == 0 ||
strcasecmp(str, "yes" ) == 0));
- /* has no user header yet... */
- info->http_user_header = 0;
+ /* user header (with optional '\r\n' added automagically) */
+ REG_VALUE(REG_CONN_HTTP_USER_HEADER, str, DEF_CONN_HTTP_USER_HEADER);
+ if (*str) {
+ size_t len = strlen(str);
+ if (str[len - 1] != '\n' && len < sizeof(str) - 2) {
+ str[len++] = '\r';
+ str[len++] = '\n';
+ str[len] = '\0';
+ }
+ info->http_user_header = strdup(str);
+ } else
+ info->http_user_header = 0;
+
/* not adjusted yet... */
info->http_proxy_adjusted = 0/*false*/;
/* store service name for which this structure has been created */
@@ -332,7 +342,7 @@ extern int/*bool*/ ConnNetInfo_ParseURL(SConnNetInfo* info, const char* url)
extern int/*bool*/ ConnNetInfo_SetUserHeader(SConnNetInfo* info,
- const char* user_header)
+ const char* user_header)
{
if (info->http_user_header)
free((void*) info->http_user_header);
@@ -703,7 +713,7 @@ extern void ConnNetInfo_Log(const SConnNetInfo* info, LOG lg)
s_SaveString (s, "path", info->path);
s_SaveString (s, "args", info->args);
s_SaveString (s, "req_method", (info->req_method == eReqMethod_Any
- ? DEF_CONN_REQ_METHOD
+ ? "ANY"
: (info->req_method
== eReqMethod_Get
? "GET"
@@ -783,10 +793,15 @@ extern SOCK URL_Connect
return 0/*error*/;
}
+ /* select request method and its verbal representation */
+ if (req_method == eReqMethod_Any) {
+ req_method = content_length ? eReqMethod_Post : eReqMethod_Get;
+ } else if (req_method == eReqMethod_Get && content_length) {
+ CORE_LOG(eLOG_Warning,
+ "[URL_Connect] Content length ignored with method GET");
+ content_length = 0;
+ }
switch (req_method) {
- case eReqMethod_Any:
- x_req_r = DEF_CONN_REQ_METHOD " ";
- break;
case eReqMethod_Post:
x_req_r = "POST ";
break;
@@ -799,11 +814,6 @@ extern SOCK URL_Connect
assert(0);
return 0/*error*/;
}
- if (content_length && strcasecmp(x_req_r, "GET ") == 0) {
- CORE_LOG(eLOG_Warning,
- "[URL_Connect] Content length ignored with GET");
- content_length = 0;
- }
/* URL-encode "args", if any specified */
if (args && *args) {
@@ -1250,6 +1260,163 @@ extern void URL_Encode
+extern void BASE64_Encode
+(const void* src_buf,
+ size_t src_size,
+ size_t* src_read,
+ void* dst_buf,
+ size_t dst_size,
+ size_t* dst_written,
+ size_t* line_len)
+{
+ static const char syms[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /*26*/
+ "abcdefghijklmnopqrstuvwxyz" /*52*/
+ "0123456789+/"; /*64*/
+ const size_t max_len = line_len ? *line_len : 76;
+ const size_t max_src =
+ ((dst_size - (max_len ? dst_size/(max_len + 1) : 0)) >> 2) * 3;
+ unsigned char* src = (unsigned char*) src_buf;
+ unsigned char* dst = (unsigned char*) dst_buf;
+ size_t len = 0, i = 0, j = 0;
+ unsigned char shift = 2;
+ unsigned char temp = 0;
+ if (!max_src) {
+ *src_read = 0;
+ *dst_written = 0;
+ if (dst_size > 0) {
+ *dst = '\0';
+ }
+ return;
+ }
+ if (src_size > max_src) {
+ src_size = max_src;
+ }
+ for (;;) {
+ unsigned char c = i < src_size ? src[i] : 0;
+ unsigned char bits = (c >> shift) & 0x3F;
+ assert((temp | bits) < sizeof(syms) - 1);
+ dst[j++] = syms[temp | bits];
+ if (max_len && ++len >= max_len) {
+ dst[j++] = '\n';
+ len = 0;
+ }
+ if (i >= src_size) {
+ break;
+ }
+ shift += 2;
+ shift &= 7;
+ if (shift) {
+ i++;
+ }
+ temp = (c << (8 - shift)) & 0x3F;
+ }
+ assert(j <= dst_size);
+ *src_read = i;
+ for (i = 0; i < (3 - src_size % 3) % 3; i++) {
+ dst[j++] = '=';
+ if (max_len && ++len >= max_len) {
+ dst[j++] = '\n';
+ len = 0;
+ }
+ }
+ assert(j <= dst_size);
+ *dst_written = j;
+ if (j < dst_size) {
+ dst[j] = '\0';
+ }
+}
+
+
+extern int/*bool*/ BASE64_Decode
+(const void* src_buf,
+ size_t src_size,
+ size_t* src_read,
+ void* dst_buf,
+ size_t dst_size,
+ size_t* dst_written)
+{
+ unsigned char* src = (unsigned char*) src_buf;
+ unsigned char* dst = (unsigned char*) dst_buf;
+ size_t i = 0, j = 0, k = 0, l;
+ unsigned int temp = 0;
+ if (src_size < 4 || dst_size < 3) {
+ *src_read = 0;
+ *dst_written = 0;
+ return 0/*false*/;
+ }
+ for (;;) {
+ unsigned char c = i < src_size ? src[i++] : '=';
+ if (c == '=') {
+ c = 64; /*end*/
+ } else if (c >= 'A' && c <= 'Z') {
+ c -= 'A';
+ } else if (c >= 'a' && c <= 'z') {
+ c -= 'a' - 26;
+ } else if (c >= '0' && c <= '9') {
+ c -= '0' - 52;
+ } else if (c == '+') {
+ c = 62;
+ } else if (c == '/') {
+ c = 63;
+ } else {
+ continue;
+ }
+ temp <<= 6;
+ temp |= c & 0x3F;
+ if (!(++k & 3) || c == 64) {
+ if (c == 64) {
+ if (k < 2) {
+ --i;
+ break;
+ }
+ switch (k) {
+ case 2:
+ temp >>= 4;
+ break;
+ case 3:
+ temp >>= 10;
+ break;
+ case 4:
+ temp >>= 8;
+ break;
+ default:
+ break;
+ }
+ for (l = k; l < 4; l++) {
+ if (i < src_size && src[i] == '=') {
+ i++;
+ }
+ }
+ } else {
+ k = 0;
+ }
+ switch (k) {
+ case 0:
+ dst[j++] = (temp & 0xFF0000) >> 16;
+ /*FALLTHRU*/;
+ case 4:
+ dst[j++] = (temp & 0xFF00) >> 8;
+ /*FALLTHRU*/
+ case 3:
+ dst[j++] = (temp & 0xFF);
+ break;
+ default:
+ break;
+ }
+ if (j + 3 >= dst_size || c == 64) {
+ break;
+ }
+ temp = 0;
+ }
+ }
+ *src_read = i;
+ *dst_written = j;
+ return i ? 1/*true*/ : 0/*false*/;
+}
+
+
+
/****************************************************************************
* NCBI-specific MIME content type and sub-types
*/
@@ -1497,6 +1664,28 @@ extern size_t HostPortToString(unsigned int host,
/*
* --------------------------------------------------------------------------
* $Log: ncbi_connutil.c,v $
+ * Revision 6.72 2005/04/20 15:50:30 lavr
+ * ConnNetInfo_Create(): Allow zero timeout
+ * URL_Connect(): Automagically figure out ANY method based upon body size
+ *
+ * Revision 6.71 2005/03/21 17:10:03 lavr
+ * BASE64_Decode(): unnecessary re-init of "k" removed
+ *
+ * Revision 6.70 2005/03/21 17:04:35 lavr
+ * BASE64_{En|De}code few bugs fixed
+ *
+ * Revision 6.69 2005/03/19 02:13:55 lavr
+ * +BASE64_{En|De}code
+ *
+ * Revision 6.68 2005/02/28 17:58:31 lavr
+ * Cosmetics
+ *
+ * Revision 6.67 2005/02/24 19:03:11 lavr
+ * Always init SConnNetInfo::http_user_header
+ *
+ * Revision 6.66 2005/02/24 19:00:45 lavr
+ * +CONN_HTTP_USER_HEADER
+ *
* Revision 6.65 2004/10/14 13:51:42 lavr
* StringToHostPort() to allow NULL ptrs
*
diff --git a/connect/ncbi_connutil.h b/connect/ncbi_connutil.h
index 344326bd..2a8c6a92 100644
--- a/connect/ncbi_connutil.h
+++ b/connect/ncbi_connutil.h
@@ -1,7 +1,7 @@
#ifndef CONNECT___NCBI_CONNUTIL__H
#define CONNECT___NCBI_CONNUTIL__H
-/* $Id: ncbi_connutil.h,v 6.36 2004/09/16 16:19:16 lavr Exp $
+/* $Id: ncbi_connutil.h,v 6.42 2005/04/20 15:47:24 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -56,23 +56,27 @@
* URL_Connect()
*
* 3.Perform URL encoding/decoding of data:
+ * URL_Encode()
* URL_Decode()
* URL_DecodeEx()
- * URL_Encode()
*
- * 4.Compose or parse NCBI-specific Content-Type's:
+ * 4.Perform BASE64 (RFC 1521) encoding/decoding of data:
+ * BASE64_Encode()
+ * BASE64_Decode()
+ *
+ * 5.Compose or parse NCBI-specific Content-Type's:
* EMIME_Type
* EMIME_SubType
* EMIME_Encoding
* MIME_ComposeContentType()
* MIME_ParseContentType()
*
- * 5.Search for a token in the input stream (either CONN or SOCK):
+ * 6.Search for a token in the input stream (either CONN or SOCK):
* CONN_StripToPattern()
* SOCK_StripToPattern()
* BUF_StripToPattern()
*
- * 6.Convert "[host][:port]" from verbal into binary form and vice versa:
+ * 7.Convert "[host][:port]" from verbal into binary form and vice versa:
* StringToHostPort()
* HostPortToString()
*
@@ -155,7 +159,7 @@ typedef struct {
#define DEF_CONN_ARGS ""
#define REG_CONN_REQ_METHOD "REQ_METHOD"
-#define DEF_CONN_REQ_METHOD "POST"
+#define DEF_CONN_REQ_METHOD "ANY"
#define REG_CONN_TIMEOUT "TIMEOUT"
#define DEF_CONN_TIMEOUT 30.0
@@ -184,6 +188,9 @@ typedef struct {
#define REG_CONN_LB_DISABLE "LB_DISABLE"
#define DEF_CONN_LB_DISABLE ""
+#define REG_CONN_HTTP_USER_HEADER "HTTP_USER_HEADER"
+#define DEF_CONN_HTTP_USER_HEADER 0
+
/* This function to fill out the "*info" structure using
* registry entries named (see above) in macros REG_CONN_<NAME>:
@@ -204,6 +211,7 @@ typedef struct {
* debug_printout DEBUG_PRINTOUT
* client_mode CLIENT_MODE
* lb_disable LB_DISABLE
+ * http_user_header HTTP_USER_HEADER "\r\n" if missing is appended
*
* A value of the field NAME is first looked for in the environment variable
* of the form service_CONN_NAME; then in the current corelib registry,
@@ -361,6 +369,7 @@ extern NCBI_XCONNECT_EXPORT void ConnNetInfo_Log
extern NCBI_XCONNECT_EXPORT void ConnNetInfo_Destroy(SConnNetInfo* info);
+
/* Hit URL "http://host:port/path?args" with:
* {POST|GET} <path>?<args> HTTP/1.0\r\n
* <user_header\r\n>
@@ -401,6 +410,7 @@ extern NCBI_XCONNECT_EXPORT SOCK URL_Connect
);
+
/* Discard all input data before(and including) the first occurrence of
* "pattern". If "buf" is not NULL then add the discarded data(including
* the "pattern") to it. If "n_discarded" is not NULL then "*n_discarded"
@@ -432,12 +442,29 @@ extern NCBI_XCONNECT_EXPORT EIO_Status BUF_StripToPattern
);
+
+/* URL-encode up to "src_size" symbols(bytes) from buffer "src_buf".
+ * Write the encoded data to buffer "dst_buf", but no more than "dst_size"
+ * bytes.
+ * Assign "*src_read" to the # of bytes successfully encoded from "src_buf".
+ * Assign "*dst_written" to the # of bytes written to buffer "dst_buf".
+ */
+extern NCBI_XCONNECT_EXPORT void URL_Encode
+(const void* src_buf, /* [in] non-NULL */
+ size_t src_size, /* [in] */
+ size_t* src_read, /* [out] non-NULL */
+ void* dst_buf, /* [in/out] non-NULL */
+ size_t dst_size, /* [in] */
+ size_t* dst_written /* [out] non-NULL */
+ );
+
+
/* URL-decode up to "src_size" symbols(bytes) from buffer "src_buf".
* Write the decoded data to buffer "dst_buf", but no more than "dst_size"
* bytes.
* Assign "*src_read" to the # of bytes successfully decoded from "src_buf".
* Assign "*dst_written" to the # of bytes written to buffer "dst_buf".
- * Return FALSE only if cannot decode nothing, and an unrecoverable
+ * Return FALSE (0) only if cannot decode anything, and an unrecoverable
* URL-encoding error (such as an invalid symbol or a bad "%.." sequence)
* has occurred.
* NOTE: the unfinished "%.." sequence is fine -- return TRUE, but dont
@@ -470,13 +497,40 @@ extern NCBI_XCONNECT_EXPORT int/*bool*/ URL_DecodeEx
);
-/* URL-encode up to "src_size" symbols(bytes) from buffer "src_buf".
+
+/* BASE64-encode up to "src_size" symbols(bytes) from buffer "src_buf".
* Write the encoded data to buffer "dst_buf", but no more than "dst_size"
* bytes.
* Assign "*src_read" to the # of bytes successfully encoded from "src_buf".
* Assign "*dst_written" to the # of bytes written to buffer "dst_buf".
+ * Resulting lines will not exceed "*line_len" (or the standard default
+ * if "line_len" is NULL) bytes; *line_len == 0 disables line breaks.
+ * To estimate required destination buffer size, you can take into account
+ * that BASE64 coding converts every 3 bytes of source into 4 bytes on
+ * destination, not including the line breaks ('\n').
*/
-extern NCBI_XCONNECT_EXPORT void URL_Encode
+extern NCBI_XCONNECT_EXPORT void BASE64_Encode
+(const void* src_buf, /* [in] non-NULL */
+ size_t src_size, /* [in] */
+ size_t* src_read, /* [out] non-NULL */
+ void* dst_buf, /* [in/out] non-NULL */
+ size_t dst_size, /* [in] */
+ size_t* dst_written,/* [out] non-NULL */
+ size_t* line_len /* [in] may be NULL */
+ );
+
+
+/* BASE64-decode up to "src_size" symbols(bytes) from buffer "src_buf".
+ * Write the decoded data to buffer "dst_buf", but no more than "dst_size"
+ * bytes.
+ * Assign "*src_read" to the # of bytes successfully decoded from "src_buf".
+ * Assign "*dst_written" to the # of bytes written to buffer "dst_buf".
+ * Return FALSE (0) only if cannot decode anything.
+ * Destination buffer size, as a worst case, equal to the source size
+ * will accomodate the entire input. As a rule, each 4 bytes of source
+ * (line breaks skipped) are converted into 3 bytes on output.
+ */
+extern NCBI_XCONNECT_EXPORT int/*bool*/ BASE64_Decode
(const void* src_buf, /* [in] non-NULL */
size_t src_size, /* [in] */
size_t* src_read, /* [out] non-NULL */
@@ -643,6 +697,24 @@ extern NCBI_XCONNECT_EXPORT size_t HostPortToString
/*
* --------------------------------------------------------------------------
* $Log: ncbi_connutil.h,v $
+ * Revision 6.42 2005/04/20 15:47:24 lavr
+ * DEF_CONN_REQ_METHOD changed to ANY
+ *
+ * Revision 6.41 2005/03/21 17:04:10 lavr
+ * BASE64_{En|De}code buffer size estimation hints added
+ *
+ * Revision 6.40 2005/03/19 02:13:55 lavr
+ * +BASE64_{En|De}code
+ *
+ * Revision 6.39 2005/02/28 17:23:20 lavr
+ * Fix HTTP_USER_HEADER env.var. name ("HTTP" was missing)
+ *
+ * Revision 6.38 2005/02/24 19:51:24 lavr
+ * Document CONN_HTTP_USER_HEADER environment
+ *
+ * Revision 6.37 2005/02/24 19:00:33 lavr
+ * +CONN_HTTP_USER_HEADER
+ *
* Revision 6.36 2004/09/16 16:19:16 lavr
* Mention [in opening comment summary] that EMIME_Type is defined here
*
diff --git a/connect/ncbi_core.c b/connect/ncbi_core.c
index 37011628..b830a288 100644
--- a/connect/ncbi_core.c
+++ b/connect/ncbi_core.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_core.c,v 6.14 2003/08/28 18:47:51 ucko Exp $
+/* $Id: ncbi_core.c,v 6.15 2005/04/20 18:13:39 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -31,6 +31,7 @@
*/
#include "ncbi_ansi_ext.h"
+#include "ncbi_assert.h"
#include <connect/ncbi_core.h>
#include <stdlib.h>
@@ -461,6 +462,9 @@ extern void REG_Set
/*
* ---------------------------------------------------------------------------
* $Log: ncbi_core.c,v $
+ * Revision 6.15 2005/04/20 18:13:39 lavr
+ * +"ncbi_assert.h"
+ *
* Revision 6.14 2003/08/28 18:47:51 ucko
* Revert previous hack (now handled another way)
*
diff --git a/connect/ncbi_core.h b/connect/ncbi_core.h
index faf6d78f..c4fd8c0b 100644
--- a/connect/ncbi_core.h
+++ b/connect/ncbi_core.h
@@ -1,7 +1,7 @@
#ifndef CONNECT___NCBI_CORE__H
#define CONNECT___NCBI_CORE__H
-/* $Id: ncbi_core.h,v 6.25 2004/03/12 23:26:22 gorelenk Exp $
+/* $Id: ncbi_core.h,v 6.27 2005/04/20 18:10:53 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -65,27 +65,6 @@
#include <connect/ncbi_types.h>
-/* Run-time debugging */
-#if defined(verify)
-#undef verify
-#endif
-
-#if !defined(NDEBUG) && !defined(_DEBUG)
-# define NDEBUG
-#endif
-#include <assert.h>
-#if defined(NDEBUG)
-# define verify(expr) (void)(expr)
-#else
-/* The following 2 headers are actually only required for Codewarrior
- * on Mac to prototype printf() and abort() respectively :-/
- */
-# include <stdio.h>
-# include <stdlib.h>
-# define verify(expr) assert(expr)
-#endif
-
-
/** @addtogroup UtilityFunc
*
* @{
@@ -119,7 +98,8 @@ typedef enum {
*/
typedef enum {
eIO_WritePlain,
- eIO_WritePersist
+ eIO_WritePersist,
+ eIO_WriteOutOfBand
} EIO_WriteMethod;
@@ -480,6 +460,12 @@ extern NCBI_XCONNECT_EXPORT void REG_Set
* ===========================================================================
*
* $Log: ncbi_core.h,v $
+ * Revision 6.27 2005/04/20 18:10:53 lavr
+ * verify() moved away into a private header (ncbi_assert.h)
+ *
+ * Revision 6.26 2004/12/27 15:30:08 lavr
+ * +eIO_WriteOutOfBand
+ *
* Revision 6.25 2004/03/12 23:26:22 gorelenk
* Added export prefixes.
*
diff --git a/connect/ncbi_core_c.c b/connect/ncbi_core_c.c
index 2e5a1a05..733220f8 100644
--- a/connect/ncbi_core_c.c
+++ b/connect/ncbi_core_c.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_core_c.c,v 6.9 2002/10/31 17:53:33 lavr Exp $
+/* $Id: ncbi_core_c.c,v 6.10 2005/04/20 20:38:42 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -34,6 +34,7 @@
*/
#include "ncbi_config.h"
+#include "ncbi_assert.h"
#include <connect/ncbi_ansi_ext.h>
#include <connect/ncbi_core_c.h>
#include <connect/ncbi_util.h>
@@ -231,6 +232,9 @@ extern void CONNECT_Init(const char* conf_file)
/*
* ---------------------------------------------------------------------------
* $Log: ncbi_core_c.c,v $
+ * Revision 6.10 2005/04/20 20:38:42 lavr
+ * +"ncbi_assert.h"
+ *
* Revision 6.9 2002/10/31 17:53:33 lavr
* Clear error in case of a trace message
*
diff --git a/connect/ncbi_dispd.c b/connect/ncbi_dispd.c
index 7907798e..a9fd7e37 100644
--- a/connect/ncbi_dispd.c
+++ b/connect/ncbi_dispd.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_dispd.c,v 6.62 2004/08/19 15:48:15 lavr Exp $
+/* $Id: ncbi_dispd.c,v 6.65 2005/04/25 18:46:13 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -42,6 +42,10 @@
#include <stdlib.h>
#include <time.h>
+#if 0/*defined(_DEBUG) && !defined(NDEBUG)*/
+# define SERV_DISPD_DEBUG 1
+#endif /*_DEBUG && !NDEBUG*/
+
/* Lower bound of up-to-date/out-of-date ratio */
#define SERV_DISPD_STALE_RATIO_OK 0.8
/* Default rate increase if svc runs locally */
@@ -55,7 +59,7 @@ static FDISP_MessageHook s_MessageHook = 0;
#ifdef __cplusplus
extern "C" {
-#endif
+#endif /*__cplusplus*/
static void s_Reset (SERV_ITER);
static SSERV_Info* s_GetNextInfo(SERV_ITER, HOST_INFO*);
static int/*bool*/ s_Update (SERV_ITER, TNCBI_Time, const char*);
@@ -66,7 +70,7 @@ extern "C" {
};
#ifdef __cplusplus
} /* extern "C" */
-#endif
+#endif /*__cplusplus*/
static int s_RandomSeed = 0;
@@ -174,9 +178,10 @@ static int/*bool*/ s_Resolve(SERV_ITER iter)
if (*net_info->client_host && !strchr(net_info->client_host, '.') &&
(ip = SOCK_gethostbyname(net_info->client_host)) != 0 &&
SOCK_ntoa(ip, addr, sizeof(addr)) == 0) {
- if ((s= malloc(strlen(net_info->client_host) + strlen(addr) + 3)) != 0)
+ if ((s = (char*) malloc(strlen(net_info->client_host) +
+ strlen(addr) + 3)) != 0) {
sprintf(s, "%s(%s)", net_info->client_host, addr);
- else
+ } else
s = net_info->client_host;
} else
s = net_info->client_host;
@@ -209,7 +214,7 @@ static int/*bool*/ s_Resolve(SERV_ITER iter)
" (C++ Toolkit)"
#else
" (C Toolkit)"
-#endif
+#endif /*NCBI_CXX_TOOLKIT*/
"\r\n");
data->disp_fail = 0;
/* All the rest in the net_info structure is fine with us */
@@ -264,7 +269,7 @@ static int/*bool*/ s_Update(SERV_ITER iter, TNCBI_Time now, const char* text)
p++;
if (data->net_info->debug_printout)
CORE_LOGF(eLOG_Warning, ("[DISPATCHER] %s", p));
-#endif
+#endif /*_DEBUG && !NDEBUG*/
data->disp_fail = 1;
return 1/*updated*/;
} else if (len >= sizeof(HTTP_DISP_MESSAGE) &&
@@ -334,11 +339,13 @@ static SSERV_Info* s_GetNextInfo(SERV_ITER iter, HOST_INFO* host_info)
status = info->rate;
assert(status != 0.0);
- if (info->host == iter->preferred_host) {
- if (info->coef <= 0.0 || iter->preference) {
+ if (iter->preferred_host == info->host ||
+ (!iter->preferred_host &&
+ info->locl && info->coef < 0.0)) {
+ if (iter->preference || info->coef <= 0.0) {
status *= SERV_DISPD_LOCAL_SVC_BONUS;
if (access < status &&
- (iter->preference || info->coef < 0.0)) {
+ (iter->preference || info->coef < 0.0)) {
access = status;
point = total + status; /* Latch this local server */
p = -info->coef;
@@ -351,19 +358,35 @@ static SSERV_Info* s_GetNextInfo(SERV_ITER iter, HOST_INFO* host_info)
data->s_node[i].status = total;
}
- if (point > 0.0 && iter->preference) {
+ if (point > 0.0 && iter->preference) {
if (total != access) {
p = SERV_Preference(iter->preference, access/total, data->n_node);
+#ifdef SERV_DISPD_DEBUG
+ CORE_LOGF(eLOG_Note, ("(P = %lf, A = %lf, T = %lf, N = %d)"
+ " -> Pref = %lf", iter->preference,
+ access, total, (int) data->n_node, p));
+#endif /*SERV_DISPD_DEBUG*/
status = total*p;
p = total*(1.0 - p)/(total - access);
for (i = 0; i < data->n_node; i++) {
data->s_node[i].status *= p;
- if (p*point <= data->s_node[i].status)
+ if (p*point <= data->s_node[i].status)
data->s_node[i].status += status - p*access;
}
+#ifdef SERV_DISPD_DEBUG
+ for (i = 0; i < data->n_node; i++) {
+ char addr[16];
+ SOCK_ntoa(data->s_node[i].info->host, addr, sizeof(addr));
+ status = data->s_node[i].status -
+ (i ? data->s_node[i-1].status : 0.0);
+ CORE_LOGF(eLOG_Note, ("%s %lf %.2lf%%", addr,
+ status, status/total*100.0));
+ }
+#endif /*SERV_DISPD_DEBUG*/
}
point = -1.0;
}
+
/* We take pre-chosen local server only if its status is not less than
p% of the average remaining status; otherwise, we ignore the server,
and apply the generic procedure by seeding a random point. */
@@ -466,6 +489,15 @@ void DISP_SetMessageHook(FDISP_MessageHook hook)
/*
* --------------------------------------------------------------------------
* $Log: ncbi_dispd.c,v $
+ * Revision 6.65 2005/04/25 18:46:13 lavr
+ * Made parallel with ncbi_lbsmd.c
+ *
+ * Revision 6.64 2005/03/16 20:15:25 lavr
+ * Allow local B services to have a preference
+ *
+ * Revision 6.63 2005/01/27 19:00:05 lavr
+ * Explicit cast of malloc()ed memory
+ *
* Revision 6.62 2004/08/19 15:48:15 lavr
* SERV_ITER::type renamed into SERV_ITER::types to reflect its bitmask nature
*
diff --git a/connect/ncbi_file_connector.c b/connect/ncbi_file_connector.c
index c055b536..86f56a3c 100644
--- a/connect/ncbi_file_connector.c
+++ b/connect/ncbi_file_connector.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_file_connector.c,v 6.12 2003/05/31 05:14:56 lavr Exp $
+/* $Id: ncbi_file_connector.c,v 6.13 2005/04/20 18:15:59 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -35,6 +35,7 @@
#include "ncbi_ansi_ext.h"
#include <connect/ncbi_file_connector.h>
+#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
@@ -324,6 +325,9 @@ extern CONNECTOR FILE_CreateConnectorEx
/*
* --------------------------------------------------------------------------
* $Log: ncbi_file_connector.c,v $
+ * Revision 6.13 2005/04/20 18:15:59 lavr
+ * +<assert.h>
+ *
* Revision 6.12 2003/05/31 05:14:56 lavr
* Add ARGSUSED where args are meant to be unused
*
diff --git a/connect/ncbi_ftp_connector.c b/connect/ncbi_ftp_connector.c
new file mode 100644
index 00000000..20239bbc
--- /dev/null
+++ b/connect/ncbi_ftp_connector.c
@@ -0,0 +1,718 @@
+/* $Id: ncbi_ftp_connector.c,v 1.7 2005/04/20 18:15:59 lavr Exp $
+ * ===========================================================================
+ *
+ * PUBLIC DOMAIN NOTICE
+ * National Center for Biotechnology Information
+ *
+ * This software/database is a "United States Government Work" under the
+ * terms of the United States Copyright Act. It was written as part of
+ * the author's official duties as a United States Government employee and
+ * thus cannot be copyrighted. This software/database is freely available
+ * to the public for use. The National Library of Medicine and the U.S.
+ * Government have not placed any restriction on its use or reproduction.
+ *
+ * Although all reasonable efforts have been taken to ensure the accuracy
+ * and reliability of the software and data, the NLM and the U.S.
+ * Government do not and cannot warrant the performance or results that
+ * may be obtained by using this software or data. The NLM and the U.S.
+ * Government disclaim all warranties, express or implied, including
+ * warranties of performance, merchantability or fitness for any particular
+ * purpose.
+ *
+ * Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author: Anton Lavrentiev
+ *
+ * File Description:
+ * FTP CONNECTOR
+ * See also: RFCs 959 (STD 9), 1634 (FYI 24),
+ * and IETF 9-2002 "Extensions to FTP".
+ *
+ * See <connect/ncbi_connector.h> for the detailed specification of
+ * the connector's methods and structures.
+ *
+ */
+
+#include "ncbi_ansi_ext.h"
+#include <connect/ncbi_buffer.h>
+#include <connect/ncbi_ftp_connector.h>
+#include <connect/ncbi_socket.h>
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+/***********************************************************************
+ * INTERNAL -- Auxiliary types and static functions
+ ***********************************************************************/
+
+
+typedef enum {
+ eFtpFeature_None = 0,
+ eFtpFeature_MDTM = 1,
+ eFtpFeature_SIZE = 2
+} EFtpFeature;
+typedef unsigned int TFtpFeatures; /* bitwise OR of individual EFtpFeature's */
+
+
+/* All internal data necessary to perform the (re)connect and i/o
+ */
+typedef struct {
+ const char* host;
+ unsigned short port;
+ const char* user;
+ const char* pass;
+ const char* path;
+ const char* name;
+ TFtpFeatures feat;
+ ESwitch log;
+ SOCK cntl; /* control connection */
+ SOCK data; /* data connection */
+ BUF wbuf; /* write buffer */
+ EIO_Status r_status;
+ EIO_Status w_status;
+} SFTPConnector;
+
+
+static EIO_Status s_ReadReply(SOCK sock, int* code,
+ char* line, size_t maxlinelen)
+{
+ int/*bool*/ first = 1/*true*/;
+ for (;;) {
+ int c, m;
+ size_t n;
+ char buf[1024];
+ EIO_Status status = SOCK_ReadLine(sock, buf, sizeof(buf), &n);
+ if (status != eIO_Success)
+ return status;
+ if (n == sizeof(buf))
+ return eIO_Unknown/*line too long*/;
+ if (first || isdigit((unsigned char) *buf)) {
+ if (sscanf(buf, "%d%n", &c, &m) < 1)
+ return eIO_Unknown;
+ } else
+ c = 0;
+ if (first) {
+ if (m != 3 || code == 0)
+ return eIO_Unknown;
+ if (line)
+ strncpy0(line, &buf[m + 1], maxlinelen);
+ *code = c;
+ if (buf[m] != '-') {
+ if (buf[m] == ' ')
+ break;
+ return eIO_Unknown;
+ }
+ first = 0/*false*/;
+ } else if (c == *code && m == 3 && buf[m] == ' ')
+ break;
+ }
+ return eIO_Success;
+}
+
+
+static EIO_Status s_FTPReply(SFTPConnector* xxx, int* code,
+ char* line, size_t maxlinelen)
+{
+ int c = 0;
+ EIO_Status status = eIO_Closed;
+ if (xxx->cntl) {
+ status = s_ReadReply(xxx->cntl, &c, line, maxlinelen);
+ if (status == eIO_Success && c == 421)
+ status = eIO_Closed;
+ if (status == eIO_Closed || (status == eIO_Success && c == 221)) {
+ SOCK_Close(xxx->cntl);
+ xxx->cntl = 0;
+ if (xxx->data) {
+ SOCK_Close(xxx->data);
+ xxx->data = 0;
+ }
+ }
+ }
+ if (code)
+ *code = c;
+ return status;
+}
+
+
+static EIO_Status s_WriteCommand(SOCK sock,
+ const char* cmd, const char* arg)
+{
+ size_t cmdlen = strlen(cmd);
+ size_t arglen = arg ? strlen(arg) : 0;
+ size_t linelen = cmdlen + (arglen ? 1/* */ + arglen : 0) + 2/*\r\n*/;
+ char* line = (char*) malloc(linelen + 1/*\0*/);
+ EIO_Status status = eIO_Unknown;
+ if (line) {
+ memcpy(line, cmd, cmdlen);
+ if (arglen) {
+ line[cmdlen++] = ' ';
+ memcpy(line + cmdlen, arg, arglen);
+ cmdlen += arglen;
+ }
+ line[cmdlen++] = '\r';
+ line[cmdlen++] = '\n';
+ line[cmdlen] = '\0';
+ status = SOCK_Write(sock, line, linelen, 0, eIO_WritePersist);
+ free(line);
+ }
+ return status;
+}
+
+
+static EIO_Status s_FTPCommand(SFTPConnector* xxx,
+ const char* cmd, const char* arg)
+{
+ return xxx->cntl ? s_WriteCommand(xxx->cntl, cmd, arg) : eIO_Closed;
+}
+
+
+static EIO_Status s_FTPLogin(SFTPConnector* xxx, const STimeout* timeout)
+{
+ EIO_Status status;
+ int code;
+
+ assert(xxx->cntl && xxx->user && xxx->pass);
+ status = SOCK_SetTimeout(xxx->cntl, eIO_ReadWrite, timeout);
+ if (status != eIO_Success)
+ return status;
+ status = s_FTPReply(xxx, &code, 0, 0);
+ if (status != eIO_Success)
+ return status;
+ if (code != 220 || !*xxx->user)
+ return eIO_Unknown;
+ status = s_FTPCommand(xxx, "USER", xxx->user);
+ if (status != eIO_Success)
+ return status;
+ status = s_FTPReply(xxx, &code, 0, 0);
+ if (status != eIO_Success)
+ return status;
+ if (code == 230)
+ return eIO_Success;
+ if (code != 331 || !*xxx->pass)
+ return eIO_Unknown;
+ status = s_FTPCommand(xxx, "PASS", xxx->pass);
+ if (status != eIO_Success)
+ return status;
+ status = s_FTPReply(xxx, &code, 0, 0);
+ if (status != eIO_Success)
+ return status;
+ if (code == 230)
+ return eIO_Success;
+ else
+ return eIO_Unknown;
+}
+
+
+static EIO_Status s_FTPChdir(SFTPConnector* xxx, const char* cmd)
+{
+ if (cmd || xxx->path) {
+ int code;
+ EIO_Status status = s_FTPCommand(xxx,
+ cmd ? cmd : "CWD",
+ cmd ? 0 : xxx->path);
+ if (status != eIO_Success)
+ return status;
+ status = s_FTPReply(xxx, &code, 0, 0);
+ if (status != eIO_Success)
+ return status;
+ if (code != 250)
+ return eIO_Unknown;
+ }
+ return eIO_Success;
+}
+
+
+static EIO_Status s_FTPBinary(SFTPConnector* xxx)
+{
+ int code;
+ EIO_Status status = s_FTPCommand(xxx, "TYPE", "I");
+ if (status != eIO_Success)
+ return status;
+ status = s_FTPReply(xxx, &code, 0, 0);
+ if (status != eIO_Success)
+ return status;
+ if (code == 200)
+ return eIO_Success;
+ else
+ return eIO_Unknown;
+}
+
+
+static EIO_Status s_FTPAbort(SFTPConnector* xxx)
+{
+ EIO_Status status = eIO_Success;
+ if (xxx->data) {
+ int code;
+ size_t n;
+ /* Send TELNET IP (Interrupt Process) command */
+ status = SOCK_Write(xxx->cntl, "\377\364", 2, &n, eIO_WritePersist);
+ if (status != eIO_Success)
+ return status;
+ if (n != 2)
+ return eIO_Unknown;
+ /* Send TELNET DM (Data Mark) command to complete SYNCH, RFC 854 */
+ status = SOCK_Write(xxx->cntl, "\377\362", 2, &n, eIO_WriteOutOfBand);
+ if (status != eIO_Success)
+ return status;
+ if (n != 2)
+ return eIO_Unknown;
+ status = s_FTPCommand(xxx, "ABOR", 0);
+ while(SOCK_Read(xxx->data, 0, 1024*1024/*drain up*/, 0, eIO_ReadPlain)
+ == eIO_Success);
+ if (status == eIO_Success)
+ status = s_FTPReply(xxx, &code, 0, 0);
+ /* Microsoft FTP is known to return 225 (instead of 226) */
+ if (status == eIO_Success && (code/100) != 2 && code != 426)
+ status = eIO_Unknown;
+ if (status == eIO_Success)
+ status = SOCK_Close(xxx->data);
+ else if (xxx->data) {
+ SOCK_Close(xxx->data);
+ xxx->data = 0;
+ }
+ }
+ return status;
+}
+
+
+static EIO_Status s_FTPPasv(SFTPConnector* xxx)
+{
+ static STimeout zero;
+ int code, o[6];
+ unsigned int i;
+ char buf[128], *c;
+ unsigned int host;
+ unsigned short port;
+
+ EIO_Status status = s_FTPCommand(xxx, "PASV", 0);
+ if (status != eIO_Success)
+ return status;
+ status = s_FTPReply(xxx, &code, buf, sizeof(buf) - 1);
+ if (status != eIO_Success || code != 227)
+ return eIO_Unknown;
+ buf[sizeof(buf) - 1] = '\0';
+ for (;;) {
+ /* RFC 1123 4.1.2.6 says that ()'s in PASV reply must not be assumed */
+ for (c = buf; *c; c++) {
+ if (isdigit((unsigned char) *c))
+ break;
+ }
+ if (!*c)
+ return eIO_Unknown;
+ if (sscanf(c, "%d,%d,%d,%d,%d,%d%n",
+ &o[0], &o[1], &o[2], &o[3], &o[4], &o[5], &code) >= 6) {
+ break;
+ }
+ strcpy(buf, c + code);
+ }
+ for (i = 0; i < (unsigned int)(sizeof(o)/sizeof(o[0])); i++) {
+ if (o[i] < 0 || o[i] > 255)
+ return eIO_Unknown;
+ }
+ i = (((((o[0] << 8) + o[1]) << 8) + o[2]) << 8) + o[3];
+ host = SOCK_htonl(i);
+ i = (o[4] << 8) + o[5];
+ port = (unsigned short) i;
+ if (SOCK_ntoa(host, buf, sizeof(buf)) == 0 &&
+ SOCK_CreateEx(buf, port, &zero, &xxx->data,
+ 0, 0, xxx->log) == eIO_Success) {
+ return eIO_Success;
+ }
+ s_FTPAbort(xxx);
+ return eIO_Unknown;
+}
+
+
+static EIO_Status s_FTPRetrieve(SFTPConnector* xxx,
+ const char* cmd)
+{
+ int code;
+ EIO_Status status = s_FTPPasv(xxx);
+ if (status != eIO_Success)
+ return status;
+ status = s_FTPCommand(xxx, cmd, 0);
+ if (status != eIO_Success)
+ return status;
+ status = s_FTPReply(xxx, &code, 0, 0);
+ if (status != eIO_Success)
+ return status;
+ if (code == 150)
+ return eIO_Success;
+ s_FTPAbort(xxx);
+ return eIO_Unknown;
+}
+
+
+static EIO_Status s_FTPQuit(SFTPConnector* xxx)
+{
+ EIO_Status status;
+ int code;
+ s_FTPAbort(xxx);
+ status = s_FTPCommand(xxx, "QUIT", 0);
+ if (status == eIO_Success)
+ status = s_FTPReply(xxx, &code, 0, 0);
+ if (status == eIO_Success && code != 221)
+ status = eIO_Unknown;
+ if (xxx->cntl) {
+ if (status == eIO_Success)
+ status = SOCK_Close(xxx->cntl);
+ else
+ SOCK_Close(xxx->cntl);
+ xxx->cntl = 0;
+ }
+ return status;
+}
+
+
+static EIO_Status s_FTPExecute(SFTPConnector* xxx, const STimeout* timeout)
+{
+ EIO_Status status = eIO_Success;
+ size_t size = BUF_Size(xxx->wbuf);
+ char* s = (char*) malloc(size + 1);
+ s_FTPAbort(xxx);
+ assert(size);
+ if (s) {
+ if (BUF_Read(xxx->wbuf, s, size) == size &&
+ SOCK_SetTimeout(xxx->cntl, eIO_ReadWrite, timeout) == eIO_Success){
+ char* c;
+ s[size] = '\0';
+ if (!(c = strchr(s, ' ')))
+ c = s + strlen(s);
+ size = (size_t)(c - s);
+ if (strncasecmp(s, "CWD", size) == 0) {
+ status = s_FTPChdir(xxx, s);
+ } else if (strncasecmp(s, "LIST", size) == 0 ||
+ strncasecmp(s, "NLST", size) == 0 ||
+ strncasecmp(s, "RETR", size) == 0) {
+ status = s_FTPRetrieve(xxx, s);
+ } else if (strncasecmp(s, "REST", size) == 0) {
+ status = s_FTPCommand(xxx, s, 0);
+ if (status == eIO_Success) {
+ int code;
+ status = s_FTPReply(xxx, &code, 0, 0);
+ if (status == eIO_Success && code != 350)
+ status = eIO_Unknown;
+ }
+ } else
+ status = eIO_Unknown;
+ } else
+ status = eIO_Unknown;
+ free(s);
+ } else
+ status = eIO_Unknown;
+ return status;
+}
+
+
+/***********************************************************************
+ * INTERNAL -- "s_VT_*" functions for the "virt. table" of connector methods
+ ***********************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+ static const char* s_VT_GetType (CONNECTOR connector);
+ static EIO_Status s_VT_Open (CONNECTOR connector,
+ const STimeout* timeout);
+ static EIO_Status s_VT_Wait (CONNECTOR connector,
+ EIO_Event event,
+ const STimeout* timeout);
+ static EIO_Status s_VT_Write (CONNECTOR connector,
+ const void* buf,
+ size_t size,
+ size_t* n_written,
+ const STimeout* timeout);
+ static EIO_Status s_VT_Read (CONNECTOR connector,
+ void* buf,
+ size_t size,
+ size_t* n_read,
+ const STimeout* timeout);
+ static EIO_Status s_VT_Flush (CONNECTOR connector,
+ const STimeout* timeout);
+ static EIO_Status s_VT_Status (CONNECTOR connector,
+ EIO_Event dir);
+ static EIO_Status s_VT_Close (CONNECTOR connector,
+ const STimeout* timeout);
+ static void s_Setup (SMetaConnector* meta,
+ CONNECTOR connector);
+ static void s_Destroy (CONNECTOR connector);
+# ifdef IMPLEMENTED__CONN_WaitAsync
+ static EIO_Status s_VT_WaitAsync(void* connector,
+ FConnectorAsyncHandler func,
+ SConnectorAsyncHandler* data);
+# endif
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+
+/*ARGSUSED*/
+static const char* s_VT_GetType
+(CONNECTOR connector)
+{
+ return "FTP";
+}
+
+
+static EIO_Status s_VT_Open
+(CONNECTOR connector,
+ const STimeout* timeout)
+{
+ SFTPConnector* xxx = (SFTPConnector*) connector->handle;
+ EIO_Status status;
+
+ assert(!xxx->data && !xxx->cntl);
+ status = SOCK_CreateEx(xxx->host, xxx->port, timeout, &xxx->cntl,
+ 0, 0, xxx->log);
+ if (status == eIO_Success)
+ status = s_FTPLogin(xxx, timeout);
+ if (status == eIO_Success)
+ status = s_FTPChdir(xxx, 0);
+ if (status == eIO_Success)
+ status = s_FTPBinary(xxx);
+ if (status != eIO_Success) {
+ if (xxx->cntl) {
+ SOCK_Close(xxx->cntl);
+ xxx->cntl = 0;
+ }
+ }
+ xxx->r_status = status;
+ xxx->w_status = status;
+ return status;
+}
+
+
+static EIO_Status s_VT_Write
+(CONNECTOR connector,
+ const void* buf,
+ size_t size,
+ size_t* n_written,
+ const STimeout* timeout)
+{
+ SFTPConnector* xxx = (SFTPConnector*) connector->handle;
+ EIO_Status status;
+ const char* c;
+ size_t s;
+
+ xxx->w_status = eIO_Success;
+ if ( !size )
+ return eIO_Success;
+ if (!xxx->cntl)
+ return eIO_Closed;
+
+ if ((c = strchr((const char*) buf, '\n')) != 0) {
+ if (c[1])
+ return eIO_Unknown;
+ if (c != buf && c[-1] == '\r')
+ c--;
+ s = (size_t)(c - (const char*) buf);
+ } else
+ s = size;
+ status = BUF_Write(&xxx->wbuf, buf, s) ? eIO_Success : eIO_Unknown;
+ if (status == eIO_Success && c) {
+ xxx->w_status = s_FTPExecute(xxx, timeout);
+ status = xxx->w_status;
+ }
+ *n_written = size;
+ return status;
+}
+
+
+static EIO_Status s_VT_Read
+(CONNECTOR connector,
+ void* buf,
+ size_t size,
+ size_t* n_read,
+ const STimeout* timeout)
+{
+ SFTPConnector* xxx = (SFTPConnector*) connector->handle;
+ EIO_Status status = eIO_Closed;
+ xxx->r_status = eIO_Success;
+ if (xxx->cntl && xxx->data) {
+ status = SOCK_SetTimeout(xxx->data, eIO_Read, timeout);
+ if (status == eIO_Success) {
+ xxx->r_status = SOCK_Read(xxx->data,
+ buf, size, n_read, eIO_ReadPlain);
+ if (xxx->r_status == eIO_Closed) {
+ int code;
+ SOCK_Close(xxx->data);
+ xxx->data = 0;
+ SOCK_SetTimeout(xxx->cntl, eIO_Read, timeout);
+ s_FTPReply(xxx, &code, 0, 0);
+ }
+ status = xxx->r_status;
+ }
+ }
+ return status;
+}
+
+
+static EIO_Status s_VT_Wait
+(CONNECTOR connector,
+ EIO_Event event,
+ const STimeout* timeout)
+{
+ SFTPConnector* xxx = (SFTPConnector*) connector->handle;
+ if (!xxx->cntl)
+ return eIO_Closed;
+ if (event & eIO_Write)
+ return eIO_Success;
+ if (!xxx->data) {
+ EIO_Status status;
+ if (!BUF_Size(xxx->wbuf))
+ return eIO_Closed;
+ if ((status = s_FTPExecute(xxx, timeout)) != eIO_Success)
+ return status;
+ if (!xxx->data)
+ return eIO_Closed;
+ }
+ return SOCK_Wait(xxx->data, eIO_Read, timeout);
+}
+
+
+static EIO_Status s_VT_Flush
+(CONNECTOR connector,
+ const STimeout* timeout)
+{
+ SFTPConnector* xxx = (SFTPConnector*) connector->handle;
+ size_t size = BUF_Size(xxx->wbuf);
+ EIO_Status status = eIO_Success;
+ if (size != 0)
+ status = s_FTPExecute(xxx, timeout);
+ return status;
+}
+
+
+static EIO_Status s_VT_Status
+(CONNECTOR connector,
+ EIO_Event dir)
+{
+ SFTPConnector* xxx = (SFTPConnector*) connector->handle;
+
+ switch (dir) {
+ case eIO_Read:
+ return xxx->r_status;
+ case eIO_Write:
+ return xxx->w_status;
+ default:
+ assert(0); /* should never happen as checked by connection */
+ return eIO_InvalidArg;
+ }
+}
+
+
+/*ARGSUSED*/
+static EIO_Status s_VT_Close
+(CONNECTOR connector,
+ const STimeout* timeout)
+{
+ SFTPConnector* xxx = (SFTPConnector*) connector->handle;
+ if (xxx->cntl)
+ SOCK_SetTimeout(xxx->cntl, eIO_ReadWrite, timeout);
+ return s_FTPQuit(xxx);
+}
+
+
+static void s_Setup
+(SMetaConnector* meta,
+ CONNECTOR connector)
+{
+ /* initialize virtual table */
+ CONN_SET_METHOD(meta, get_type, s_VT_GetType, connector);
+ CONN_SET_METHOD(meta, open, s_VT_Open, connector);
+ CONN_SET_METHOD(meta, wait, s_VT_Wait, connector);
+ CONN_SET_METHOD(meta, write, s_VT_Write, connector);
+ CONN_SET_METHOD(meta, flush, s_VT_Flush, connector);
+ CONN_SET_METHOD(meta, read, s_VT_Read, connector);
+ CONN_SET_METHOD(meta, status, s_VT_Status, connector);
+ CONN_SET_METHOD(meta, close, s_VT_Close, connector);
+#ifdef IMPLEMENTED__CONN_WaitAsync
+ CONN_SET_METHOD(meta, wait_async, s_VT_WaitAsync, connector);
+#endif
+ meta->default_timeout = 0/*infinite*/;
+}
+
+
+static void s_Destroy
+(CONNECTOR connector)
+{
+ SFTPConnector* xxx = (SFTPConnector*) connector->handle;
+ free((void*) xxx->host);
+ free((void*) xxx->user);
+ free((void*) xxx->pass);
+ if (xxx->path)
+ free((void*) xxx->path);
+ if (xxx->name)
+ free((void*) xxx->name);
+ BUF_Destroy(xxx->wbuf);
+ free(xxx);
+ connector->handle = 0;
+ free(connector);
+}
+
+
+/***********************************************************************
+ * EXTERNAL -- the connector's "constructors"
+ ***********************************************************************/
+
+extern CONNECTOR FTP_CreateDownloadConnector(const char* host,
+ unsigned short port,
+ const char* user,
+ const char* pass,
+ const char* path,
+ ESwitch log)
+{
+ CONNECTOR ccc = (SConnector*) malloc(sizeof(SConnector));
+ SFTPConnector* xxx = (SFTPConnector*) malloc(sizeof(*xxx));
+
+ xxx->data = 0;
+ xxx->cntl = 0;
+ xxx->wbuf = 0;
+ xxx->host = strdup(host);
+ xxx->port = port ? port : 21;
+ xxx->user = strdup(user ? user : "ftp");
+ xxx->pass = strdup(pass ? pass : "none");
+ xxx->path = path && *path ? strdup(path) : 0;
+ xxx->name = 0;
+ xxx->log = log;
+ /* initialize connector data */
+ ccc->handle = xxx;
+ ccc->next = 0;
+ ccc->meta = 0;
+ ccc->setup = s_Setup;
+ ccc->destroy = s_Destroy;
+
+ return ccc;
+}
+
+
+/*
+ * --------------------------------------------------------------------------
+ * $Log: ncbi_ftp_connector.c,v $
+ * Revision 1.7 2005/04/20 18:15:59 lavr
+ * +<assert.h>
+ *
+ * Revision 1.6 2005/01/27 18:59:52 lavr
+ * Explicit cast of malloc()ed memory
+ *
+ * Revision 1.5 2005/01/05 17:40:13 lavr
+ * FEAT extensions and fixes for protocol compliance
+ *
+ * Revision 1.4 2004/12/27 15:31:27 lavr
+ * Implement telnet SYNCH and FTP ABORT according to the standard
+ *
+ * Revision 1.3 2004/12/08 21:03:26 lavr
+ * Fixes for default ctor parameters
+ *
+ * Revision 1.2 2004/12/07 14:21:55 lavr
+ * Init wbuf in ctor
+ *
+ * Revision 1.1 2004/12/06 17:48:38 lavr
+ * Initial revision
+ *
+ * ==========================================================================
+ */
diff --git a/connect/ncbi_ftp_connector.h b/connect/ncbi_ftp_connector.h
new file mode 100644
index 00000000..d7c6ca44
--- /dev/null
+++ b/connect/ncbi_ftp_connector.h
@@ -0,0 +1,84 @@
+#ifndef CONNECT___NCBI_FTP_CONNECTOR__H
+#define CONNECT___NCBI_FTP_CONNECTOR__H
+
+/* $Id: ncbi_ftp_connector.h,v 1.1 2004/12/06 17:48:19 lavr Exp $
+ * ===========================================================================
+ *
+ * PUBLIC DOMAIN NOTICE
+ * National Center for Biotechnology Information
+ *
+ * This software/database is a "United States Government Work" under the
+ * terms of the United States Copyright Act. It was written as part of
+ * the author's official duties as a United States Government employee and
+ * thus cannot be copyrighted. This software/database is freely available
+ * to the public for use. The National Library of Medicine and the U.S.
+ * Government have not placed any restriction on its use or reproduction.
+ *
+ * Although all reasonable efforts have been taken to ensure the accuracy
+ * and reliability of the software and data, the NLM and the U.S.
+ * Government do not and cannot warrant the performance or results that
+ * may be obtained by using this software or data. The NLM and the U.S.
+ * Government disclaim all warranties, express or implied, including
+ * warranties of performance, merchantability or fitness for any particular
+ * purpose.
+ *
+ * Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author: Anton Lavrentiev
+ *
+ * File Description:
+ * FTP CONNECTOR
+ *
+ * See <connect/ncbi_connector.h> for the detailed specification of
+ * the connector's methods and structures.
+ *
+ */
+
+#include <connect/ncbi_buffer.h>
+#include <connect/ncbi_connector.h>
+
+
+/** @addtogroup Connectors
+ *
+ * @{
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Create new CONNECTOR structure to handle ftp download transfer.
+ * Return NULL on error.
+ */
+extern NCBI_XCONNECT_EXPORT CONNECTOR FTP_CreateDownloadConnector
+(const char* host, /* hostname, required */
+ unsigned short port, /* port #, 21 [standard] if 0 passed here */
+ const char* user, /* username, "ftp" [==anonymous] by default */
+ const char* pass, /* password, "none" by default */
+ const char* path, /* initial directory to chdir to on open */
+ ESwitch log /* whether to turn on socket debugging [optional] */
+);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+/* @} */
+
+
+/*
+ * --------------------------------------------------------------------------
+ * $Log: ncbi_ftp_connector.h,v $
+ * Revision 1.1 2004/12/06 17:48:19 lavr
+ * Initial revision
+ *
+ * ==========================================================================
+ */
+
+#endif /* CONNECT___NCBI_FTP_CONNECTOR__H */
diff --git a/connect/ncbi_heapmgr.c b/connect/ncbi_heapmgr.c
index 7a2767f5..6b9dab8c 100644
--- a/connect/ncbi_heapmgr.c
+++ b/connect/ncbi_heapmgr.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_heapmgr.c,v 6.26 2003/10/02 14:52:23 lavr Exp $
+/* $Id: ncbi_heapmgr.c,v 6.27 2005/01/27 19:00:17 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -181,7 +181,7 @@ HEAP HEAP_AttachEx(const void* base, TNCBI_Size size)
{
HEAP heap;
- if (!base || !size || !(heap = malloc(sizeof(*heap))))
+ if (!base || !size || !(heap = (HEAP) malloc(sizeof(*heap))))
return 0;
if ((void*) HEAP_ALIGN(base) != base) {
CORE_LOGF(eLOG_Warning,
@@ -573,6 +573,9 @@ int HEAP_Serial(const HEAP heap)
/*
* --------------------------------------------------------------------------
* $Log: ncbi_heapmgr.c,v $
+ * Revision 6.27 2005/01/27 19:00:17 lavr
+ * Explicit cast of malloc()ed memory
+ *
* Revision 6.26 2003/10/02 14:52:23 lavr
* Wrapped long lines in the change log
*
diff --git a/connect/ncbi_http_connector.c b/connect/ncbi_http_connector.c
index 1d57a475..61d508fa 100644
--- a/connect/ncbi_http_connector.c
+++ b/connect/ncbi_http_connector.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_http_connector.c,v 6.63 2004/02/12 16:50:02 lavr Exp $
+/* $Id: ncbi_http_connector.c,v 6.65 2005/03/08 16:23:13 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -415,12 +415,11 @@ static EIO_Status s_ReadHeader(SHttpConnector* uuu, char** redirect)
/* skip & printout the content, if server error was flagged */
if (server_error && uuu->net_info->debug_printout == eDebugPrintout_Some) {
BUF buf = 0;
- EIO_Status status;
char* body;
SOCK_SetTimeout(uuu->sock, eIO_Read, 0);
- status = SOCK_StripToPattern(uuu->sock, 0, 0, &buf, 0);
- assert(status != eIO_Success); /* because reading until EOF */
+ /* because reading until EOF the verify below holds */
+ verify(SOCK_StripToPattern(uuu->sock, 0, 0, &buf, 0) != eIO_Success);
if (!(size = BUF_Size(buf))) {
CORE_LOG(eLOG_Trace, "[HTTP] No body received with this error");
} else if ((body = (char*) malloc(size)) != 0) {
@@ -918,7 +917,7 @@ extern CONNECTOR HTTP_CreateConnector
net_info = info ? ConnNetInfo_Clone(info) : ConnNetInfo_Create(0);
if (user_header)
- ConnNetInfo_SetUserHeader(net_info, user_header);
+ ConnNetInfo_OverrideUserHeader(net_info, user_header);
connector = HTTP_CreateConnectorEx(net_info, flags, 0, 0, 0, 0);
ConnNetInfo_Destroy(net_info);
return connector;
@@ -976,6 +975,12 @@ extern CONNECTOR HTTP_CreateConnectorEx
/*
* --------------------------------------------------------------------------
* $Log: ncbi_http_connector.c,v $
+ * Revision 6.65 2005/03/08 16:23:13 lavr
+ * Replace an assert() with verify() to remove release-mode unused var
+ *
+ * Revision 6.64 2005/02/28 17:59:07 lavr
+ * HTTP_CreateConnector() to "override" addtl. user header instead of "set"
+ *
* Revision 6.63 2004/02/12 16:50:02 lavr
* Heed warning about uninited variable use
*
diff --git a/connect/ncbi_memory_connector.c b/connect/ncbi_memory_connector.c
index 260316a2..965fa9cb 100644
--- a/connect/ncbi_memory_connector.c
+++ b/connect/ncbi_memory_connector.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_memory_connector.c,v 6.5 2003/05/31 05:15:39 lavr Exp $
+/* $Id: ncbi_memory_connector.c,v 6.8 2005/04/20 18:15:59 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -35,6 +35,7 @@
#include <connect/ncbi_buffer.h>
#include <connect/ncbi_memory_connector.h>
+#include <assert.h>
#include <stdlib.h>
@@ -45,10 +46,11 @@
/* All internal data necessary to perform the (re)connect and i/o
*/
typedef struct {
- BUF buf;
- MT_LOCK lock;
- EIO_Status r_status;
- EIO_Status w_status;
+ BUF buf;
+ MT_LOCK lock;
+ int/*bool*/ own_buf;
+ EIO_Status r_status;
+ EIO_Status w_status;
} SMemoryConnector;
@@ -106,7 +108,6 @@ static EIO_Status s_VT_Open
const STimeout* timeout)
{
SMemoryConnector* xxx = (SMemoryConnector*) connector->handle;
- xxx->buf = 0;
xxx->r_status = eIO_Success;
xxx->w_status = eIO_Success;
return eIO_Success;
@@ -201,7 +202,7 @@ static EIO_Status s_VT_Close
const STimeout* timeout)
{
SMemoryConnector* xxx = (SMemoryConnector*) connector->handle;
- BUF_Destroy(xxx->buf);
+ BUF_Erase(xxx->buf);
return eIO_Success;
}
@@ -230,7 +231,8 @@ static void s_Destroy
(CONNECTOR connector)
{
SMemoryConnector* xxx = (SMemoryConnector*) connector->handle;
-
+ if (xxx->own_buf)
+ BUF_Destroy(xxx->buf);
free(xxx);
connector->handle = 0;
free(connector);
@@ -243,11 +245,19 @@ static void s_Destroy
extern CONNECTOR MEMORY_CreateConnector(MT_LOCK lock)
{
+ return MEMORY_CreateConnectorEx(0, lock);
+}
+
+
+extern CONNECTOR MEMORY_CreateConnectorEx(BUF buf, MT_LOCK lock)
+{
CONNECTOR ccc = (SConnector*) malloc(sizeof(SConnector));
SMemoryConnector* xxx = (SMemoryConnector*) malloc(sizeof(*xxx));
/* initialize internal data structures */
+ xxx->buf = buf;
xxx->lock = lock;
+ xxx->own_buf = buf ? 0/*false*/ : 1/*true*/;
/* initialize connector data */
ccc->handle = xxx;
@@ -263,6 +273,15 @@ extern CONNECTOR MEMORY_CreateConnector(MT_LOCK lock)
/*
* --------------------------------------------------------------------------
* $Log: ncbi_memory_connector.c,v $
+ * Revision 6.8 2005/04/20 18:15:59 lavr
+ * +<assert.h>
+ *
+ * Revision 6.7 2004/10/27 19:16:33 lavr
+ * Reuse MEMORY_CreateConnectorEx() in MEMORY_CreateConnector()
+ *
+ * Revision 6.6 2004/10/27 18:44:56 lavr
+ * +MEMORY_CreateConnectorEx() and not-owned buffer management
+ *
* Revision 6.5 2003/05/31 05:15:39 lavr
* Add ARGSUSED where args are meant to be unused, remove Flush
*
diff --git a/connect/ncbi_memory_connector.h b/connect/ncbi_memory_connector.h
index 93512514..cd172992 100644
--- a/connect/ncbi_memory_connector.h
+++ b/connect/ncbi_memory_connector.h
@@ -1,7 +1,7 @@
#ifndef CONNECT___NCBI_MEMORY_CONNECTOR__H
#define CONNECT___NCBI_MEMORY_CONNECTOR__H
-/* $Id: ncbi_memory_connector.h,v 6.4 2003/04/09 19:05:45 siyan Exp $
+/* $Id: ncbi_memory_connector.h,v 6.5 2004/10/27 18:44:14 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -36,6 +36,7 @@
*
*/
+#include <connect/ncbi_buffer.h>
#include <connect/ncbi_connector.h>
@@ -57,6 +58,9 @@ extern "C" {
extern NCBI_XCONNECT_EXPORT CONNECTOR MEMORY_CreateConnector(MT_LOCK lock);
+extern NCBI_XCONNECT_EXPORT CONNECTOR MEMORY_CreateConnectorEx(BUF buf,
+ MT_LOCK lock);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
@@ -68,6 +72,9 @@ extern NCBI_XCONNECT_EXPORT CONNECTOR MEMORY_CreateConnector(MT_LOCK lock);
/*
* --------------------------------------------------------------------------
* $Log: ncbi_memory_connector.h,v $
+ * Revision 6.5 2004/10/27 18:44:14 lavr
+ * +MEMORY_CreateConnectorEx()
+ *
* Revision 6.4 2003/04/09 19:05:45 siyan
* Added doxygen support
*
diff --git a/connect/ncbi_priv.h b/connect/ncbi_priv.h
index 3b3b1e6f..9ea87e46 100644
--- a/connect/ncbi_priv.h
+++ b/connect/ncbi_priv.h
@@ -1,7 +1,7 @@
#ifndef CONNECT___NCBI_PRIV__H
#define CONNECT___NCBI_PRIV__H
-/* $Id: ncbi_priv.h,v 6.10 2004/03/12 23:25:37 gorelenk Exp $
+/* $Id: ncbi_priv.h,v 6.11 2005/04/20 18:14:10 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -41,6 +41,7 @@
*
*/
+#include "ncbi_assert.h"
#include <connect/ncbi_util.h>
@@ -183,6 +184,9 @@ extern NCBI_XCONNECT_EXPORT char* g_CORE_RegistryGET
/*
* ---------------------------------------------------------------------------
* $Log: ncbi_priv.h,v $
+ * Revision 6.11 2005/04/20 18:14:10 lavr
+ * +"ncbi_assert.h"
+ *
* Revision 6.10 2004/03/12 23:25:37 gorelenk
* Added export prefixes.
*
diff --git a/connect/ncbi_sendmail.c b/connect/ncbi_sendmail.c
index bf3c4bc8..a0b85953 100644
--- a/connect/ncbi_sendmail.c
+++ b/connect/ncbi_sendmail.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_sendmail.c,v 6.22 2004/01/07 19:51:36 lavr Exp $
+/* $Id: ncbi_sendmail.c,v 6.23 2005/03/18 16:35:39 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -419,8 +419,9 @@ const char* CORE_SendMailEx(const char* to,
CORE_LOG(eLOG_Warning,"[SendMail] Subject ignored in as-is messages");
if (!s_SockWrite(sock, "X-Mailer: CORE_SendMail (NCBI "
- NCBI_SENDMAIL_TOOLKIT " Toolkit)" MX_CRLF))
+ NCBI_SENDMAIL_TOOLKIT " Toolkit)" MX_CRLF)) {
SENDMAIL_RETURN("Write error in sending mailer information");
+ }
assert(sizeof(buffer) > sizeof(MX_CRLF) && sizeof(MX_CRLF) >= 3);
@@ -435,7 +436,7 @@ const char* CORE_SendMailEx(const char* to,
k += sizeof(MX_CRLF) - 1;
newline = 1/*true*/;
} else {
- if (info->header[n] != '\r' || !newline)
+ if (info->header[n] != '\r' || info->header[n+1] != '\n')
buffer[k++] = info->header[n];
newline = 0/*false*/;
}
@@ -465,7 +466,7 @@ const char* CORE_SendMailEx(const char* to,
k += sizeof(MX_CRLF) - 1;
newline = 1/*true*/;
} else {
- if (body[n] != '\r' || !newline) {
+ if (body[n] != '\r' || (n+1 < m && body[n+1] != '\n')){
if (body[n] == '.' && (newline || !n)) {
buffer[k++] = '.';
buffer[k++] = '.';
@@ -508,6 +509,9 @@ const char* CORE_SendMailEx(const char* to,
/*
* ---------------------------------------------------------------------------
* $Log: ncbi_sendmail.c,v $
+ * Revision 6.23 2005/03/18 16:35:39 lavr
+ * Fix \r\n parse bug in both header and body
+ *
* Revision 6.22 2004/01/07 19:51:36 lavr
* Try to obtain user name from USERNAME env.var. on Windows, else fallback
*
diff --git a/connect/ncbi_sendmail.h b/connect/ncbi_sendmail.h
index ef2f3881..6894fe2f 100644
--- a/connect/ncbi_sendmail.h
+++ b/connect/ncbi_sendmail.h
@@ -1,7 +1,7 @@
#ifndef CONNECT___NCBI_SENDMAIL__H
#define CONNECT___NCBI_SENDMAIL__H
-/* $Id: ncbi_sendmail.h,v 6.16 2003/12/09 15:38:02 lavr Exp $
+/* $Id: ncbi_sendmail.h,v 6.17 2005/04/28 14:18:12 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -72,8 +72,8 @@ typedef struct {
/* NOTE about recipient lists:
* They are not parsed; valid recipient (according to the standard)
* can be specified in the form "Name" <address>; recipients should
- * be separated by commas. In case of address-only recipients (no "Name"
- * part above), angle brackets around the address may be omitted.
+ * be separated by commas. In case of address-only recipients (with no
+ * "Name" part above), angle brackets around the address may be omitted.
*
* NOTE about message body size:
* If not specified (0) and by default the message body size is calculated
@@ -148,6 +148,9 @@ extern NCBI_XCONNECT_EXPORT const char* CORE_SendMailEx
/*
* --------------------------------------------------------------------------
* $Log: ncbi_sendmail.h,v $
+ * Revision 6.17 2005/04/28 14:18:12 lavr
+ * A bit of clarification about multiple/single email address formats
+ *
* Revision 6.16 2003/12/09 15:38:02 lavr
* +SSendMailInfo::body_size and remarks about its use
*
diff --git a/connect/ncbi_server_info.c b/connect/ncbi_server_info.c
index 090d3311..ed6438fd 100644
--- a/connect/ncbi_server_info.c
+++ b/connect/ncbi_server_info.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_server_info.c,v 6.53 2003/09/02 21:21:42 lavr Exp $
+/* $Id: ncbi_server_info.c,v 6.54 2005/04/20 18:15:59 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -32,6 +32,7 @@
#include "ncbi_ansi_ext.h"
#include "ncbi_server_infop.h"
+#include <assert.h>
#include <ctype.h>
#include <math.h>
#include <stdio.h>
@@ -838,6 +839,9 @@ static const SSERV_Attr* s_GetAttrByTag(const char* tag)
/*
* --------------------------------------------------------------------------
* $Log: ncbi_server_info.c,v $
+ * Revision 6.54 2005/04/20 18:15:59 lavr
+ * +<assert.h>
+ *
* Revision 6.53 2003/09/02 21:21:42 lavr
* Cleanup included headers
*
diff --git a/connect/ncbi_service.c b/connect/ncbi_service.c
index 4c254c54..0d37c804 100644
--- a/connect/ncbi_service.c
+++ b/connect/ncbi_service.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_service.c,v 6.55 2004/08/19 15:48:35 lavr Exp $
+/* $Id: ncbi_service.c,v 6.61 2005/04/25 18:47:29 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -132,7 +132,9 @@ static SERV_ITER s_Open(const char* service, TSERV_Type types,
unsigned int preferred_host, double preference,
const SConnNetInfo* net_info,
const SSERV_Info* const skip[], size_t n_skip,
- SSERV_Info** info, HOST_INFO* host_info, int external)
+ SSERV_Info** info, HOST_INFO* host_info,
+ int/*bool*/ external, unsigned int origin,
+ const char* arg, const char* val)
{
const char* s = s_ServiceName(service, 0);
const SSERV_VTable* op;
@@ -142,6 +144,7 @@ static SERV_ITER s_Open(const char* service, TSERV_Type types,
return 0;
iter->service = s;
+ iter->current = 0;
iter->types = types;
iter->preferred_host = preferred_host == SERV_LOCALHOST
? SOCK_gethostbyname(0) : preferred_host;
@@ -153,6 +156,11 @@ static SERV_ITER s_Open(const char* service, TSERV_Type types,
iter->op = 0;
iter->data = 0;
iter->external = external;
+ iter->origin = origin;
+ iter->arg = arg;
+ iter->arglen = arg ? strlen(arg) : 0;
+ iter->val = val;
+ iter->vallen = val ? strlen(val) : 0;
if (n_skip) {
size_t i;
@@ -203,17 +211,20 @@ SERV_ITER SERV_OpenEx(const char* service,
const SConnNetInfo* net_info,
const SSERV_Info* const skip[], size_t n_skip)
{
- return s_Open(service, types, preferred_host, 0.0,
- net_info, skip, n_skip, 0, 0, 0/*not external*/);
+ return s_Open(service, types, preferred_host, 0.0/*preference*/,
+ net_info, skip, n_skip, 0/*info*/, 0/*host_info*/,
+ 0/*not external*/, 0/*origin*/, 0/*arg*/, 0/*val*/);
}
SERV_ITER SERV_OpenP(const char* service, TSERV_Type types,
unsigned int preferred_host, double preference,
- int/*bool*/ external)
+ int/*bool*/ external, SConnNetInfo* net_info,
+ unsigned int origin, const char* arg, const char* val)
{
return s_Open(service, types, preferred_host, preference,
- 0, 0, 0, 0, 0, external);
+ net_info, 0/*skip*/, 0/*n_skip*/, 0/*info*/, 0/*hinfo*/,
+ external, origin, arg, val);
}
@@ -221,11 +232,14 @@ static SSERV_Info* s_GetInfo(const char* service, TSERV_Type types,
unsigned int preferred_host, double preference,
const SConnNetInfo* net_info,
const SSERV_Info* const skip[], size_t n_skip,
- HOST_INFO* host_info, int/*bool*/ external)
+ HOST_INFO* host_info,
+ int/*bool*/ external, unsigned int origin,
+ const char* arg, const char* val)
{
SSERV_Info* info = 0;
SERV_ITER iter= s_Open(service, types, preferred_host, preference,
- net_info, skip, n_skip, &info, host_info, external);
+ net_info, skip, n_skip, &info, host_info,
+ external, origin, arg, val);
if (iter && !info && iter->op && iter->op->GetNextInfo)
info = (*iter->op->GetNextInfo)(iter, host_info);
SERV_Close(iter);
@@ -239,17 +253,20 @@ SSERV_Info* SERV_GetInfoEx(const char* service, TSERV_Type types,
const SSERV_Info* const skip[], size_t n_skip,
HOST_INFO* host_info)
{
- return s_GetInfo(service, types, preferred_host, 0.0,
- net_info, skip, n_skip, host_info, 0/*not external*/);
+ return s_GetInfo(service, types, preferred_host, 0.0/*preference*/,
+ net_info, skip, n_skip, host_info,
+ 0/*not external*/, 0/*origin*/, 0/*arg*/, 0/*val*/);
}
SSERV_Info* SERV_GetInfoP(const char* service, TSERV_Type types,
unsigned int preferred_host, double preference,
- int/*bool*/ external)
+ int/*bool*/ external, SConnNetInfo* net_info,
+ unsigned int origin, const char* arg,const char* val)
{
return s_GetInfo(service, types, preferred_host, preference,
- 0, 0, 0, 0, external);
+ net_info, 0/*skip*/, 0/*n_skip*/, 0/*host_info*/,
+ external, origin, arg, val);
}
@@ -302,10 +319,16 @@ const char* SERV_MapperName(SERV_ITER iter)
}
+const char* SERV_GetCurrentName(SERV_ITER iter)
+{
+ return iter->current ? iter->current : iter->service;
+}
+
+
int/*bool*/ SERV_Penalize(SERV_ITER iter, double fine)
{
if (!iter || !iter->op || !iter->op->Penalize || !iter->last)
- return 0;
+ return 0/*false*/;
return (*iter->op->Penalize)(iter, fine);
}
@@ -321,6 +344,10 @@ void SERV_Reset(SERV_ITER iter)
size_t i;
if (!iter)
return;
+ if (iter->current) {
+ free((void*) iter->current);
+ iter->current = 0;
+ }
for (i = 0; i < iter->n_skip; i++)
free(iter->skip[i]);
iter->n_skip = 0;
@@ -393,6 +420,7 @@ char* SERV_PrintEx(SERV_ITER iter, const SConnNetInfo* referrer)
static const char referrer_header[] = "Referer: "/*standard misspelling*/;
static const char client_revision[] = "Client-Revision: %hu.%hu\r\n";
static const char accepted_types[] = "Accepted-Server-Types:";
+ static const char server_count[] = "Server-Count: all\r\n";
char buffer[128], *str;
TSERV_Type types, t;
size_t buflen, i;
@@ -467,6 +495,13 @@ char* SERV_PrintEx(SERV_ITER iter, const SConnNetInfo* referrer)
return 0;
}
}
+ /* how many for the dispatcher to send to us */
+ if (iter->preference) {
+ if (!BUF_Write(&buf, server_count, sizeof(server_count) - 1)) {
+ BUF_Destroy(buf);
+ return 0;
+ }
+ }
/* Drop any outdated skip entries */
s_SkipSkip(iter);
/* Put all the rest into rejection list */
@@ -522,21 +557,41 @@ char* SERV_Print(SERV_ITER iter)
*/
double SERV_Preference(double pref, double gap, unsigned int n)
{
+ double spread;
assert(0.0 <= pref && pref <= 1.0);
assert(0.0 < gap && gap <= 1.0);
assert(n >= 2);
if (gap >= pref)
return gap;
- else if (gap >= 0.75*(1.0/(double) n))
+ spread = 14.0/(n + 12.0);
+ if (gap >= spread*(1.0/(double) n))
return pref;
else
- return 2.5*gap*pref;
+ return 2.0/spread*gap*pref;
}
/*
* --------------------------------------------------------------------------
* $Log: ncbi_service.c,v $
+ * Revision 6.61 2005/04/25 18:47:29 lavr
+ * Private API to accept SConnNetInfo* for network dispatching to work too
+ *
+ * Revision 6.60 2005/04/19 16:32:19 lavr
+ * Cosmetics
+ *
+ * Revision 6.59 2005/03/05 21:05:26 lavr
+ * +SERV_ITER::current; +SERV_GetCurrentName()
+ *
+ * Revision 6.58 2005/01/31 17:09:55 lavr
+ * Argument affinity moved into service iterator
+ *
+ * Revision 6.57 2005/01/05 19:15:26 lavr
+ * Do not use C99-compliant declaration, kills MSVC compilation
+ *
+ * Revision 6.56 2005/01/05 17:39:07 lavr
+ * SERV_Preference() modified to use better load distribution
+ *
* Revision 6.55 2004/08/19 15:48:35 lavr
* SERV_ITER::type renamed into SERV_ITER::types to reflect its bitmask nature
*
diff --git a/connect/ncbi_service.h b/connect/ncbi_service.h
index 4e7c81f2..a11db9d0 100644
--- a/connect/ncbi_service.h
+++ b/connect/ncbi_service.h
@@ -1,7 +1,7 @@
#ifndef CONNECT___NCBI_SERVICE__H
#define CONNECT___NCBI_SERVICE__H
-/* $Id: ncbi_service.h,v 6.34 2004/08/19 15:26:54 lavr Exp $
+/* $Id: ncbi_service.h,v 6.36 2005/03/05 21:04:11 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -62,11 +62,11 @@ typedef struct SSERV_IterTag* SERV_ITER;
/* Create an iterator for the iterative server lookup.
- * Connection information 'info' can be a NULL pointer, which means
- * not to make any network connections (only LBSMD will be consulted).
- * If 'info' is not NULL, LBSMD is consulted first (unless 'info->lb_disable'
- * is non-zero, meaning to skip LBSMD), and then DISPD is consulted
- * (using the information provided) but only if mapping with LBSMD (if any)
+ * Connection information 'net_info' can be a NULL pointer, which means
+ * not to make any network connections (only LBSMD will be consulted). If
+ * 'net_info' is not NULL, LBSMD is consulted first (unless 'net_info->lb_disable'
+ * is non-zero, meaning to skip LBSMD), and then DISPD is consulted (using
+ * the information provided) but only if mapping with LBSMD (if any)
* has failed. This scheme permits to use any combination of service mappers.
* Note that if 'info' is not NULL then non-zero value of 'info->stateless'
* forces 'types' to have 'fSERV_StatelessOnly' set.
@@ -91,6 +91,8 @@ extern NCBI_XCONNECT_EXPORT SERV_ITER SERV_OpenSimple
/* Can be combined in types to get even dead services (not off ones!) */
#define fSERV_Promiscuous 0x80000000
+/* Do reverse DNS translation of the resulting info */
+#define fSERV_ReverseDns 0x40000000
extern NCBI_XCONNECT_EXPORT SERV_ITER SERV_OpenEx
@@ -202,6 +204,12 @@ extern NCBI_XCONNECT_EXPORT void DISP_SetMessageHook(FDISP_MessageHook);
/*
* --------------------------------------------------------------------------
* $Log: ncbi_service.h,v $
+ * Revision 6.36 2005/03/05 21:04:11 lavr
+ * +fSERV_ReverseDns
+ *
+ * Revision 6.35 2005/01/31 17:08:35 lavr
+ * info -> net_info where appropriate for consistency
+ *
* Revision 6.34 2004/08/19 15:26:54 lavr
* +fSERV_Promiscuous
*
diff --git a/connect/ncbi_servicep.h b/connect/ncbi_servicep.h
index 44b68738..0552dc6c 100644
--- a/connect/ncbi_servicep.h
+++ b/connect/ncbi_servicep.h
@@ -1,7 +1,7 @@
#ifndef CONNECT___NCBI_SERVICEP__H
#define CONNECT___NCBI_SERVICEP__H
-/* $Id: ncbi_servicep.h,v 6.25 2004/08/19 15:48:04 lavr Exp $
+/* $Id: ncbi_servicep.h,v 6.29 2005/04/25 18:47:29 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -57,26 +57,38 @@ typedef struct {
/* Iterator structure
*/
struct SSERV_IterTag {
- const char* service; /* requested service name */
- TSERV_Type types; /* requested server type(s) */
- unsigned int preferred_host; /* preferred host to select, network b.o. */
- double preference; /* range [0..100] %% */
- SSERV_Info** skip; /* servers to skip */
- size_t n_skip; /* number of servers in the array */
- size_t n_max_skip; /* number of allocated slots in the array */
- SSERV_Info* last; /* last server info taken out */
-
- const SSERV_VTable* op; /* table of virtual functions */
-
- void* data; /* private data field */
- int/*bool*/ external; /* true for mapping of external requests */
+ const char* service; /* requested service name, private storage */
+ const char* current; /* current service name, private storage */
+ TSERV_Type types; /* requested server type(s) */
+ unsigned int preferred_host; /* preferred host to select, network b.o. */
+ double preference; /* range [0..100] %% */
+ SSERV_Info** skip; /* servers to skip */
+ size_t n_skip; /* number of servers in the array */
+ size_t n_max_skip; /* number of allocated slots in the array */
+ SSERV_Info* last; /* last server info taken out */
+
+ const SSERV_VTable* op; /* table of virtual functions */
+
+ void* data; /* private data field */
+ int/*bool*/ external; /* whether this is an external request */
+ unsigned int origin; /* IP of the origin */
+ const char* arg; /* argument to match; original pointer */
+ size_t arglen; /* == 0 for NULL pointer above */
+ const char* val; /* value to match; original pointer */
+ size_t vallen; /* == 0 for NULL pointer above */
};
-/* Modified 'fast track' routine for one-shot obtaining of a service info.
+/* Modified 'fast track' routine for obtaining of a service info in one-shot.
* Please see <connect/ncbi_service.h> for explanations [SERV_GetInfoEx()].
* For now, this call is to exclusively support MYgethostbyname() replacement
- * of standard gethostbyname() libcall in apache Web daemon (see in daemons/).
+ * of standard gethostbyname() libcall in Apache Web daemon (see in daemons/).
+ *
+ * CAUTION: unlike "service" parameter, "arg" and "val" are not copied from,
+ * but the orignal pointers get stored -- take this into account
+ * while dealing with dynamically allocated strings in the slow
+ * "iterator" version of the call below -- the pointers must remain
+ * valid as long as the iterator stays open (i.e. until SERV_Close()).
*
* NOTE: Preference 0.0 does not prohibit the preferred_host to be selected;
* nor preference 100.0 ultimately opts for the preferred_host; rather,
@@ -90,7 +102,11 @@ SSERV_Info* SERV_GetInfoP
TSERV_Type types, /* mask of type(s) of servers requested */
unsigned int preferred_host,/* preferred host to use service on, nbo */
double preference, /* [0=min..100=max] preference in %% */
- int/*bool*/ external /* whether mapping is not local to NCBI */
+ int/*bool*/ external, /* whether mapping is not local to NCBI */
+ SConnNetInfo* net_info, /* for connection to dispatcher, m.b. 0 */
+ unsigned int origin, /* origin IP */
+ const char* arg, /* environment variable name to search */
+ const char* val /* environment variable value to match */
);
/* same as the above but creates an iterator to get services one by one */
@@ -99,10 +115,19 @@ SERV_ITER SERV_OpenP
TSERV_Type type,
unsigned int preferred_host,
double preference,
- int/*bool*/ external
+ int/*bool*/ external,
+ SConnNetInfo* net_info,
+ unsigned int origin,
+ const char* arg,
+ const char* val
);
+/* Return service name the iterator is currently working on.
+ */
+const char* SERV_GetCurrentName(SERV_ITER iter);
+
+
/* Private interface: update mapper information from the given text
* (<CR><LF> separated lines, usually taken from HTTP header).
*/
@@ -155,6 +180,18 @@ double SERV_Preference(double pref, double gap, unsigned int n);
/*
* --------------------------------------------------------------------------
* $Log: ncbi_servicep.h,v $
+ * Revision 6.29 2005/04/25 18:47:29 lavr
+ * Private API to accept SConnNetInfo* for network dispatching to work too
+ *
+ * Revision 6.28 2005/04/19 16:33:00 lavr
+ * More comments on how things work (SERV_{GetInfo|Open}P)
+ *
+ * Revision 6.27 2005/03/05 21:05:07 lavr
+ * +SERV_ITER::current; +SERV_GetCurrentName()
+ *
+ * Revision 6.26 2005/01/31 17:09:34 lavr
+ * Argument affinity moved into service iterator
+ *
* Revision 6.25 2004/08/19 15:48:04 lavr
* SERV_ITER::type renamed into SERV_ITER::types to reflect its bitmask nature
*
diff --git a/connect/ncbi_socket.c b/connect/ncbi_socket.c
index 16346a81..eae06402 100644
--- a/connect/ncbi_socket.c
+++ b/connect/ncbi_socket.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_socket.c,v 6.149 2004/09/08 15:12:43 ucko Exp $
+/* $Id: ncbi_socket.c,v 6.174 2005/04/25 18:48:04 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -37,8 +37,8 @@
*/
#include "ncbi_ansi_ext.h"
#include "ncbi_priv.h"
-/* The next header implicitly includes <connect/ncbi_socket.h> */
#include <connect/ncbi_connutil.h>
+#include <connect/ncbi_socket_unix.h>
/* OS must be specified in the command-line ("-D....") or in the conf. header
*/
@@ -46,7 +46,6 @@
# error "Unknown OS, must be one of NCBI_OS_UNIX, NCBI_OS_MSWIN, NCBI_OS_MAC!"
#endif /*supported platforms*/
-
/* Uncomment these(or specify "-DHAVE_GETADDRINFO -DHAVE_GETNAMEINFO") only if:
* 0) you are compiling this outside of the NCBI C or C++ Toolkits
* (USE_NCBICONF is not #define'd), and
@@ -99,6 +98,9 @@
# include <fcntl.h>
# include <sys/socket.h>
# include <netinet/in.h>
+# ifndef NCBI_COMPILER_METROWERKS
+# include <netinet/tcp.h>
+# endif
# if !defined(NCBI_OS_BEOS) && !defined(NCBI_COMPILER_MW_MSL)
# include <arpa/inet.h>
# endif /*NCBI_OS_BEOS*/
@@ -106,7 +108,7 @@
# include <sys/un.h>
#elif defined(NCBI_OS_MSWIN)
-# ifndef COMP_METRO
+# ifndef NCBI_COMPILER_METROWERKS
# include <winsock2.h>
# else
# define SD_RECEIVE 0x00
@@ -127,7 +129,6 @@
# error "Unsupported platform, must be one of NCBI_OS_UNIX, NCBI_OS_MSWIN, NCBI_OS_MAC !!!"
#endif /* platform-specific headers (for UNIX, MSWIN, MAC) */
-
/* Portable standard C headers
*/
#include <errno.h>
@@ -254,6 +255,11 @@ typedef int TSOCK_Handle;
#endif /*NCBI_OS_MSWIN, NCBI_OS_UNIX, NCBI_OS_MAC*/
+#ifdef sun
+#undef sun
+#endif
+
+
#ifdef HAVE_SOCKLEN_T
typedef socklen_t SOCK_socklen_t;
#else
@@ -288,12 +294,12 @@ typedef unsigned EBSockType;
/* Listening socket
*/
-struct LSOCK_tag {
+typedef struct LSOCK_tag {
TSOCK_Handle sock; /* OS-specific socket handle */
unsigned int id; /* the internal ID (see also "s_ID_Counter") */
unsigned int n_accept; /* total number of accepted clients */
- unsigned short port; /* port on which the socket is listening */
+ unsigned short port; /* port on which listening (host byte order) */
/* type, status, EOF, log, read-on-write etc bit-field indicators */
EBSwitch log:2; /* how to log events and data for this socket*/
@@ -304,12 +310,16 @@ struct LSOCK_tag {
unsigned/*bool*/ eof:1; /* 0 */
EBIO_Status w_status:3; /* MBZ (NB: eIO_Success) */
unsigned/*bool*/ pending:1; /* 0 */
-};
+
+#ifdef NCBI_OS_UNIX
+ char path[1]; /* must go last */
+#endif /*NCBI_OS_UNIX*/
+} LSOCK_struct;
-/* Socket [it must be in one-2-one correspondence with LSOCK above]
+/* Socket [it must be in one-2-one binary correspondence with LSOCK above]
*/
-struct SOCK_tag {
+typedef struct SOCK_tag {
TSOCK_Handle sock; /* OS-specific socket handle */
unsigned int id; /* the internal ID (see also "s_ID_Counter") */
@@ -350,12 +360,13 @@ struct SOCK_tag {
size_t n_in; /* DSOCK: msg #; SOCK: total # of bytes read */
size_t n_out; /* DSOCK: msg #; SOCK: total # of bytes sent */
+ unsigned short myport; /* this socket's port number, host byte order*/
+
#ifdef NCBI_OS_UNIX
- /* filename for UNIX socket */
- char file[1]; /* must go last */
+ /* pathname for UNIX socket */
+ char path[1]; /* must go last */
#endif /*NCBI_OS_UNIX*/
-};
-
+} SOCK_struct;
/*
@@ -609,8 +620,9 @@ static const char* s_ID(const SOCK sock, char* buf)
*/
static void s_DoLog
(const SOCK sock, EIO_Event event,
- const void* data, size_t size, const struct sockaddr* sa)
+ const void* data, size_t size, const void* ptr)
{
+ const struct sockaddr* sa = (const struct sockaddr*) ptr;
char head[128];
char tail[128];
char _id[32];
@@ -669,8 +681,10 @@ static void s_DoLog
sprintf(tail + strlen(tail), ", msg# %u",
(unsigned)(event == eIO_Read ? sock->n_in : sock->n_out));
} else {
- assert(sa == 0);
- *tail = 0;
+ if (sa)
+ strncpy0(tail, " OUT-OF-BAND", sizeof(tail) - 1);
+ else
+ *tail = '\0';
}
sprintf(head, "%s%s%s at offset %lu%s%s", s_ID(sock, _id),
event == eIO_Read
@@ -683,7 +697,8 @@ static void s_DoLog
(event == eIO_Read ? " while reading" : " while writing"),
(unsigned long) (event == eIO_Read
? sock->n_read : sock->n_written),
- sa ? (event == eIO_Read ? " from " : " to ") : "", tail);
+ sock->type == eSOCK_Datagram && sa
+ ? (event == eIO_Read ? " from " : " to ") : "", tail);
CORE_DATA(data, size, head);
break;
case eIO_Close:
@@ -736,7 +751,7 @@ extern ESwitch SOCK_SetDataLoggingAPI(ESwitch log)
extern ESwitch SOCK_SetDataLogging(SOCK sock, ESwitch log)
{
- ESwitch old = sock->log;
+ ESwitch old = (ESwitch) sock->log;
sock->log = log;
return old;
}
@@ -759,6 +774,14 @@ extern void SOCK_AllowSigPipeAPI(void)
#if 0/*defined(_DEBUG) && !defined(NDEBUG)*/
+# ifndef SOCK_HAVE_SHOWDATALAYOUT
+# define SOCK_HAVE_SHOWDATALAYOUT 1
+# endif
+
+#endif /*_DEBUG && !NDEBUG*/
+
+#ifdef SOCK_HAVE_SHOWDATALAYOUT
+
# if !defined(__GNUC__) && !defined(offsetof)
# define offsetof(T, F) ((size_t)((char*) &(((T*) 0)->F) - (char*) 0))
# endif
@@ -787,9 +810,10 @@ static void s_ShowDataLayout(void)
"\tn_read: %u\n"
"\tn_written: %u\n"
"\tn_in: %u\n"
- "\tn_out: %u"
+ "\tn_out: %u\n"
+ "\tmyport: %u"
# ifdef NCBI_OS_UNIX
- "\n\tfile: %u"
+ "\n\tpath: %u"
# endif /*NCBI_OS_UNIX*/
, (unsigned int) sizeof(SOCK_struct),
(unsigned int) offsetof(SOCK_struct, sock),
@@ -811,14 +835,15 @@ static void s_ShowDataLayout(void)
(unsigned int) offsetof(SOCK_struct, n_read),
(unsigned int) offsetof(SOCK_struct, n_written),
(unsigned int) offsetof(SOCK_struct, n_in),
- (unsigned int) offsetof(SOCK_struct, n_out)
+ (unsigned int) offsetof(SOCK_struct, n_out),
+ (unsigned int) offsetof(SOCK_struct, myport)
# ifdef NCBI_OS_UNIX
- , (unsigned int) offsetoff(SOCK_struct, file)
+ , (unsigned int) offsetof(SOCK_struct, path)
# endif /*NCBI_OS_UNIX*/
));
}
-#endif
+#endif /*SOCK_HAVE_SHOWDATALAYOUT*/
extern EIO_Status SOCK_InitializeAPI(void)
@@ -831,9 +856,9 @@ extern EIO_Status SOCK_InitializeAPI(void)
return eIO_Success;
}
-#if 0/*defined(_DEBUG) && !defined(NDEBUG)*/
+#ifdef SOCK_HAVE_SHOWDATALAYOUT
s_ShowDataLayout();
-#endif
+#endif /*SOCK_HAVE_SHOWDATALAYOUT*/
#if defined(NCBI_OS_MSWIN)
{{
@@ -912,6 +937,7 @@ static STimeout *s_tv2to(const struct timeval* tv, STimeout* to)
return to;
}
+
static struct timeval* s_to2tv(const STimeout* to, struct timeval* tv)
{
if ( !to )
@@ -964,9 +990,9 @@ static EIO_Status s_Status(SOCK sock, EIO_Event direction)
switch ( direction ) {
case eIO_Read:
return sock->type != eSOCK_Datagram && sock->eof
- ? eIO_Closed : sock->r_status;
+ ? eIO_Closed : (EIO_Status) sock->r_status;
case eIO_Write:
- return sock->w_status;
+ return (EIO_Status) sock->w_status;
default:
/*should never get here*/
assert(0);
@@ -1053,6 +1079,13 @@ static EIO_Status s_Select(size_t n,
if (polls[i].event &&
(EIO_Event)(polls[i].event | eIO_ReadWrite) == eIO_ReadWrite) {
TSOCK_Handle fd = polls[i].sock->sock;
+#if !defined(NCBI_OS_MSWIN) && defined(FD_SETSIZE)
+ if (fd >= FD_SETSIZE) {
+ polls[i].revent = eIO_Close;
+ ready = 1;
+ continue;
+ }
+#endif /*!NCBI_MSWIN && FD_SETSIZE*/
if (fd != SOCK_INVALID) {
int/*bool*/ ls = IS_LISTENING(polls[i].sock);
if (!ls && n != 1 && polls[i].sock->type == eSOCK_Datagram)
@@ -1104,6 +1137,14 @@ static EIO_Status s_Select(size_t n,
FD_SET(fd, &e_fds);
if (n_fds < (int) fd)
n_fds = (int) fd;
+#ifdef NCBI_OS_MSWIN
+ /* Check whether FD_SETSIZE has been overcome */
+ if (!FD_ISSET(fd, &e_fds)) {
+ polls[i].revent = eIO_Close;
+ ready = 1;
+ continue;
+ }
+#endif
} else {
polls[i].revent = eIO_Close;
ready = 1;
@@ -1136,7 +1177,11 @@ static EIO_Status s_Select(size_t n,
if ( !tv )
continue;
if ( s_Less(s_SelectTimeout, &x_tv) ) {
- x_tv.tv_sec -= s_SelectTimeout->tv_sec;
+ x_tv.tv_sec -= s_SelectTimeout->tv_sec;
+ if (x_tv.tv_usec < s_SelectTimeout->tv_usec) {
+ x_tv.tv_sec--;
+ x_tv.tv_usec += 1000000;
+ }
x_tv.tv_usec -= s_SelectTimeout->tv_usec;
continue;
}
@@ -1172,7 +1217,7 @@ static EIO_Status s_Select(size_t n,
if (fd != SOCK_INVALID) {
if (!write_only && FD_ISSET(fd, &r_fds))
polls[i].revent = eIO_Read;
- if (!read_only && FD_ISSET(fd, &w_fds))
+ if (!read_only && FD_ISSET(fd, &w_fds))
polls[i].revent = (EIO_Event)(polls[i].revent | eIO_Write);
if (!polls[i].revent && FD_ISSET(fd, &e_fds))
polls[i].revent = eIO_Close;
@@ -1196,10 +1241,13 @@ static EIO_Status s_Select(size_t n,
extern const STimeout* SOCK_SetSelectInternalRestartTimeout(const STimeout* t)
{
- static struct timeval s_NewTmo;
- static STimeout s_OldTmo;
- const STimeout* retval = s_tv2to(s_SelectTimeout, &s_OldTmo);
- s_SelectTimeout = s_to2tv(t, &s_NewTmo);
+ static struct timeval s_NewTmo;
+ static STimeout s_OldTmo;
+ const STimeout* retval;
+ CORE_LOCK_WRITE;
+ retval = s_tv2to(s_SelectTimeout, &s_OldTmo);
+ s_SelectTimeout = s_to2tv(t, &s_NewTmo);
+ CORE_UNLOCK;
return retval;
}
@@ -1209,31 +1257,42 @@ extern const STimeout* SOCK_SetSelectInternalRestartTimeout(const STimeout* t)
* LISTENING SOCKET
*/
-extern EIO_Status LSOCK_Create(unsigned short port,
- unsigned short backlog,
- LSOCK* lsock)
+static EIO_Status s_CreateListening(const char* path,
+ unsigned short port,
+ unsigned short backlog,
+ LSOCK* lsock,
+ TLSCE_Flags flags)
{
- return LSOCK_CreateEx(port, backlog, lsock, fLSCE_LogDefault);
-}
-
+ ESwitch log = (ESwitch)(flags & 0xF);
+ unsigned int x_id = ++s_ID_Counter;
+ TSOCK_Handle x_lsock;
+ SOCK_socklen_t addrlen;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+#ifdef NCBI_OS_UNIX
+ struct sockaddr_un sun;
+#endif /*NCBI_OS_UNIX*/
+ } addr;
+ char s[80];
+ const char* c;
-extern EIO_Status LSOCK_CreateEx(unsigned short port,
- unsigned short backlog,
- LSOCK* lsock,
- TLSCE_Flags flags)
-{
- ESwitch log = (ESwitch)(flags & 0xF);
- unsigned int x_id = ++s_ID_Counter;
- TSOCK_Handle x_lsock;
- struct sockaddr_in addr;
- unsigned int ip;
*lsock = 0;
-
/* initialize internals */
verify(s_Initialized || SOCK_InitializeAPI() == eIO_Success);
+ assert(!!path ^ !!port);
+
+ if (path) {
+#ifdef NCBI_OS_UNIX
+ addr.sa.sa_family = AF_UNIX;
+#else
+ return eIO_NotSupported;
+#endif
+ } else
+ addr.sa.sa_family = AF_INET;
/* create new(listening) socket */
- if ((x_lsock = socket(AF_INET, SOCK_STREAM, 0)) == SOCK_INVALID) {
+ if ((x_lsock = socket(addr.sa.sa_family, SOCK_STREAM, 0)) == SOCK_INVALID){
int x_errno = SOCK_ERRNO;
CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
("LSOCK#%u[?]: [LSOCK::Create] "
@@ -1241,39 +1300,53 @@ extern EIO_Status LSOCK_CreateEx(unsigned short port,
return eIO_Unknown;
}
- /*
- * It was confirmed(?) that at least under Solaris 2.5 this precaution:
- * 1) makes the address released immediately after the process
- * termination;
- * 2) still issue EADDINUSE error on the attempt to bind() to the
- * same address being in-use by a living process (if SOCK_STREAM).
- */
- if ( !s_SetReuseAddress(x_lsock, 1/*true*/) ) {
- int x_errno = SOCK_ERRNO;
- CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
- ("LSOCK#%u[%u]: [LSOCK::Create] "
- " Failed setsockopt(REUSEADDR)",
- x_id, (unsigned int) x_lsock));
- SOCK_CLOSE(x_lsock);
- return eIO_Unknown;
+ if ( port ) {
+ /*
+ * It was confirmed(?) that at least under Solaris 2.5 this precaution:
+ * 1) makes the address released immediately after the process
+ * termination;
+ * 2) still issue EADDRINUSE error on the attempt to bind() to the
+ * same address being in-use by a living process (if SOCK_STREAM).
+ */
+ if ( !s_SetReuseAddress(x_lsock, 1/*true*/) ) {
+ int x_errno = SOCK_ERRNO;
+ CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
+ ("LSOCK#%u[%u]: [LSOCK::Create] "
+ " Failed setsockopt(REUSEADDR)",
+ x_id, (unsigned int) x_lsock));
+ SOCK_CLOSE(x_lsock);
+ return eIO_Unknown;
+ }
}
/* bind */
- ip = flags & fLSCE_BindLocal ? INADDR_LOOPBACK : INADDR_ANY;
memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(ip);
- addr.sin_port = htons(port);
+#ifdef NCBI_OS_UNIX
+ if ( path ) {
+ addrlen = sizeof(addr.sun);
+ addr.sun.sun_family = AF_UNIX;
+ strncpy0(addr.sun.sun_path, path, sizeof(addr.sun.sun_path) - 1);
+ c = path;
+ } else
+#endif /*NCBI_OS_UNIX*/
+ {
+ unsigned int ip =
+ flags & fLSCE_BindLocal ? INADDR_LOOPBACK : INADDR_ANY;
+ addrlen = sizeof(addr.sin);
+ addr.sin.sin_family = AF_INET;
+ addr.sin.sin_addr.s_addr = htonl(ip);
+ addr.sin.sin_port = htons(port);
#ifdef HAVE_SIN_LEN
- addr.sin_len = sizeof(addr);
+ addr.sin.sin_len = addrlen;
#endif /*HAVE_SIN_LEN*/
- if (bind(x_lsock, (struct sockaddr*) &addr, sizeof(addr)) != 0) {
+ c = HostPortToString(htonl(ip), port, s, sizeof(s)) ? s : "?:?";
+ }
+ if (bind(x_lsock, &addr.sa, addrlen) != 0) {
int x_errno = SOCK_ERRNO;
CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
("LSOCK#%u[%u]: [LSOCK::Create] "
- " Failed bind(%s:%hu)", x_id,
- (unsigned int) x_lsock,
- ip == INADDR_LOOPBACK ? "127.0.0.1" : "", port));
+ " Failed bind(%s)", x_id,
+ (unsigned int) x_lsock, c));
SOCK_CLOSE(x_lsock);
return x_errno == SOCK_EADDRINUSE ? eIO_Closed : eIO_Unknown;
}
@@ -1282,8 +1355,9 @@ extern EIO_Status LSOCK_CreateEx(unsigned short port,
if (listen(x_lsock, backlog) != 0) {
int x_errno = SOCK_ERRNO;
CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
- ("LSOCK#%u[%u]: [LSOCK::Create] Failed listen(%hu)"
- , x_id, (unsigned int) x_lsock, backlog));
+ ("LSOCK#%u[%u]: [LSOCK::Create] Failed "
+ "listen(%hu) at %s", x_id, (unsigned int) x_lsock,
+ backlog, s));
SOCK_CLOSE(x_lsock);
return eIO_Unknown;
}
@@ -1298,32 +1372,70 @@ extern EIO_Status LSOCK_CreateEx(unsigned short port,
}
/* allocate memory for the internal socket structure */
- if ( !(*lsock = (LSOCK) calloc(1, sizeof(**lsock))) )
+ if (!(*lsock = (LSOCK)calloc(1, sizeof(**lsock) + (path?strlen(path):0)))){
return eIO_Unknown;
+ }
(*lsock)->sock = x_lsock;
+ (*lsock)->port = port;
(*lsock)->id = x_id;
(*lsock)->log = log;
(*lsock)->i_on_sig = eDefault;
+#ifdef NCBI_OS_UNIX
+ if ( path )
+ strcpy((*lsock)->path, path);
+#endif /*NCBI_OS_UNIX*/
SET_LISTENING(*lsock);
/* statistics & logging */
if (log == eOn || (log == eDefault && s_Log == eOn)) {
- CORE_LOGF(eLOG_Trace,("LSOCK#%u[%u]: Listening at %s:%hu",
- x_id, (unsigned int) x_lsock,
- ip == INADDR_LOOPBACK ? "127.0.0.1" : "", port));
+ CORE_LOGF(eLOG_Trace,("LSOCK#%u[%u]: Listening on %s",
+ x_id, (unsigned int) x_lsock, c));
}
return eIO_Success;
}
+extern EIO_Status LSOCK_Create(unsigned short port,
+ unsigned short backlog,
+ LSOCK* lsock)
+{
+ return s_CreateListening(0, port, backlog, lsock, fLSCE_LogDefault);
+}
+
+
+extern EIO_Status LSOCK_CreateEx(unsigned short port,
+ unsigned short backlog,
+ LSOCK* lsock,
+ TLSCE_Flags flags)
+{
+ return s_CreateListening(0, port, backlog, lsock, flags);
+}
+
+
+extern EIO_Status LSOCK_CreateUNIX(const char* path,
+ unsigned short backlog,
+ LSOCK* lsock,
+ ESwitch log)
+{
+ return s_CreateListening(path, 0, backlog, lsock, log);
+}
+
+
extern EIO_Status LSOCK_Accept(LSOCK lsock,
const STimeout* timeout,
SOCK* sock)
{
- struct sockaddr_in addr;
- unsigned int x_id;
- TSOCK_Handle x_sock;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+#ifdef NCBI_OS_UNIX
+ struct sockaddr_un sun;
+#endif /*NCBI_OS_UNIX*/
+ } addr;
+ unsigned int x_id;
+ TSOCK_Handle x_sock;
+ SOCK_socklen_t addrlen;
if (lsock->sock == SOCK_INVALID) {
CORE_LOGF(eLOG_Error, ("LSOCK#%u[?]: [LSOCK::Accept] "
@@ -1348,52 +1460,74 @@ extern EIO_Status LSOCK_Accept(LSOCK lsock,
}}
x_id = (lsock->id * 1000 + ++s_ID_Counter) * 1000;
- {{ /* accept next connection */
- SOCK_socklen_t addrlen = (SOCK_socklen_t) sizeof(addr);
- memset(&addr, 0, sizeof(addr));
+
+ /* accept next connection */
+ memset(&addr, 0, sizeof(addr));
+#ifdef NCBI_OS_UNIX
+ if ( lsock->path[0] ) {
+ addrlen = sizeof(addr.sun);
+ } else
+#endif /*NCBI_OS_UNIX*/
+ {
+ addrlen = sizeof(addr.sin);
#ifdef HAVE_SIN_LEN
- addr.sin_len = sizeof(addr);
-#endif
- if ((x_sock = accept(lsock->sock, (struct sockaddr*) &addr, &addrlen))
- == SOCK_INVALID) {
- int x_errno = SOCK_ERRNO;
- CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
- ("LSOCK#%u[%u]: [LSOCK::Accept] "
- " Failed accept()", lsock->id,
- (unsigned int) lsock->sock));
- return eIO_Unknown;
- }
- lsock->n_accept++;
- assert(addr.sin_family == AF_INET);
- /* man accept(2) notes that non-blocking state may not be inherited */
- if ( !s_SetNonblock(x_sock, 1/*true*/) ) {
- CORE_LOGF(eLOG_Error, ("SOCK#%u[%u]: [LSOCK::Accept] Cannot"
- " set accepted socket to non-blocking mode",
- x_id, (unsigned int) x_sock));
- SOCK_CLOSE(x_sock);
- return eIO_Unknown;
+ addr.sin.sin_len = sizeof(addr);
+#endif /*HAVE_SIN_LEN*/
}
+ if ((x_sock = accept(lsock->sock, &addr.sa, &addrlen)) == SOCK_INVALID) {
+ int x_errno = SOCK_ERRNO;
+ CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
+ ("LSOCK#%u[%u]: [LSOCK::Accept] "
+ " Failed accept()", lsock->id,
+ (unsigned int) lsock->sock));
+ return eIO_Unknown;
+ }
+ lsock->n_accept++;
+ /* man accept(2) notes that non-blocking state may not be inherited */
+ if ( !s_SetNonblock(x_sock, 1/*true*/) ) {
+ CORE_LOGF(eLOG_Error, ("SOCK#%u[%u]: [LSOCK::Accept] Cannot"
+ " set accepted socket to non-blocking mode",
+ x_id, (unsigned int) x_sock));
+ SOCK_CLOSE(x_sock);
+ return eIO_Unknown;
+ }
- if (s_ReuseAddress && !s_SetReuseAddress(x_sock, 1/*true*/)) {
- int x_errno = SOCK_ERRNO;
- CORE_LOGF_ERRNO_EX(eLOG_Warning, x_errno, SOCK_STRERROR(x_errno),
- ("SOCK#%u[%u]: [LSOCK::Accept] "
- " Failed setsockopt(REUSEADDR)",
- x_id, (unsigned int) x_sock));
- }
- }}
+ if (s_ReuseAddress &&
+#ifdef NCBI_OS_UNIX
+ !lsock->path[0] &&
+#endif /*NCBI_OS_UNIX*/
+ !s_SetReuseAddress(x_sock, 1/*true*/)) {
+ int x_errno = SOCK_ERRNO;
+ CORE_LOGF_ERRNO_EX(eLOG_Warning, x_errno, SOCK_STRERROR(x_errno),
+ ("SOCK#%u[%u]: [LSOCK::Accept] "
+ " Failed setsockopt(REUSEADDR)",
+ x_id, (unsigned int) x_sock));
+ }
/* create new SOCK structure */
- if ( !(*sock = (SOCK) calloc(1, sizeof(**sock))) ) {
+#ifdef NCBI_OS_UNIX
+ if ( lsock->path[0] )
+ addrlen = strlen(lsock->path);
+ else
+#endif /*NCBI_OS_UNIX*/
+ addrlen = 0;
+ if ( !(*sock = (SOCK) calloc(1, sizeof(**sock) + addrlen)) ) {
SOCK_CLOSE(x_sock);
return eIO_Unknown;
}
/* success */
+#ifdef NCBI_OS_UNIX
+ if ( lsock->path[0] ) {
+ strcpy((*sock)->path, lsock->path);
+ } else
+#endif /*NCBI_OS_UNIX*/
+ {
+ (*sock)->host = addr.sin.sin_addr.s_addr;
+ (*sock)->port = addr.sin.sin_port;
+ }
(*sock)->sock = x_sock;
(*sock)->id = x_id;
- (*sock)->host = addr.sin_addr.s_addr;
- (*sock)->port = addr.sin_port;
(*sock)->log = lsock->log;
(*sock)->type = eSOCK_ServerSide;
(*sock)->r_on_w = eDefault;
@@ -1408,7 +1542,7 @@ extern EIO_Status LSOCK_Accept(LSOCK lsock,
/* statistics & logging */
if (lsock->log == eOn || (lsock->log == eDefault && s_Log == eOn))
- s_DoLog(*sock, eIO_Open, 0, 0, (struct sockaddr*) &addr);
+ s_DoLog(*sock, eIO_Open, 0, 0, &addr.sa);
return eIO_Success;
}
@@ -1417,6 +1551,8 @@ extern EIO_Status LSOCK_Accept(LSOCK lsock,
extern EIO_Status LSOCK_Close(LSOCK lsock)
{
EIO_Status status;
+ const char* c;
+ char s[80];
if (lsock->sock == SOCK_INVALID) {
CORE_LOGF(eLOG_Error, ("LSOCK#%u[?]: [LSOCK::Close] "
@@ -1432,11 +1568,20 @@ extern EIO_Status LSOCK_Close(LSOCK lsock)
lsock->id, (unsigned int) lsock->sock));
}
+#ifdef NCBI_OS_UNIX
+ if ( lsock->path[0] ) {
+ c = lsock->path;
+ } else
+#endif /*NCBI_OS_UNIX*/
+ {
+ c = HostPortToString(0, lsock->port, s, sizeof(s)) ? s : ":?";
+ }
+
/* statistics & logging */
if (lsock->log == eOn || (lsock->log == eDefault && s_Log == eOn)) {
- CORE_LOGF(eLOG_Trace, ("LSOCK#%u[%u]: Closing at port :%hu "
+ CORE_LOGF(eLOG_Trace, ("LSOCK#%u[%u]: Closing at %s "
"(%u accept%s total)", lsock->id,
- (unsigned int) lsock->sock, lsock->port,
+ (unsigned int) lsock->sock, c,
lsock->n_accept, lsock->n_accept == 1? "":"s"));
}
@@ -1459,6 +1604,11 @@ extern EIO_Status LSOCK_Close(LSOCK lsock)
/* cleanup & return */
lsock->sock = SOCK_INVALID;
+#ifdef NCBI_OS_UNIX
+ if ( lsock->path[0] )
+ remove(lsock->path);
+#endif
+
free(lsock);
return status;
}
@@ -1523,6 +1673,26 @@ static EIO_Status s_IsConnected(SOCK sock,
status = eIO_Unknown;
}
#endif /*NCBI_OS_UNIX || NCBI_OS_MSWIN*/
+#if defined(_DEBUG) && !defined(NDEBUG)
+ if (status == eIO_Success) {
+# ifdef NCBI_OS_UNIX
+ if (!sock->path[0])
+# endif /*NCBI_OS_UNIX*/
+ {
+ struct sockaddr_in addr;
+ SOCK_socklen_t addrlen = sizeof(addr);
+ memset(&addr, 0, addrlen);
+# ifdef HAVE_SIN_LEN
+ addr.sin_len = addrlen;
+# endif /*HAVE_SIN_LEN*/
+ if (getsockname(sock->sock,
+ (struct sockaddr*) &addr, &addrlen) == 0) {
+ assert(addr.sin_family == AF_INET);
+ sock->myport = ntohs(addr.sin_port);
+ }
+ }
+ }
+#endif /*_DEBUG && !_NDEBUG*/
if (status != eIO_Success || poll.revent != eIO_Write) {
if ( !*x_errno )
*x_errno = SOCK_ERRNO;
@@ -1530,7 +1700,11 @@ static EIO_Status s_IsConnected(SOCK sock,
sock->r_status = sock->w_status = status = eIO_Closed;
else if (status == eIO_Success)
status = eIO_Unknown;
- } else if (s_ReuseAddress && !s_SetReuseAddress(sock->sock, 1/*true*/)) {
+ } else if (s_ReuseAddress &&
+#ifdef NCBI_OS_UNIX
+ !sock->path[0] &&
+#endif /*NCBI_OS_UNIX*/
+ !s_SetReuseAddress(sock->sock, 1/*true*/)) {
int x_errno = SOCK_ERRNO;
char _id[32];
CORE_LOGF_ERRNO_EX(eLOG_Warning, x_errno, SOCK_STRERROR(x_errno),
@@ -1541,7 +1715,7 @@ static EIO_Status s_IsConnected(SOCK sock,
}
-/* Connect the (pre-allocated) socket to the specified "host:port" peer.
+/* Connect the (pre-allocated) socket to the specified "host:port"/"file" peer.
* HINT: if "host" is NULL then assume(!) that the "sock" already exists,
* and connect to the same host; the same is for zero "port".
* NOTE: Client-side stream sockets only.
@@ -1554,33 +1728,59 @@ static EIO_Status s_Connect(SOCK sock,
char _id[32];
int x_errno;
TSOCK_Handle x_sock;
- unsigned int x_host;
- unsigned short x_port;
- struct sockaddr_in peer;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+#ifdef NCBI_OS_UNIX
+ struct sockaddr_un sun;
+#endif /*NCBI_OS_UNIX*/
+ } addr;
+ SOCK_socklen_t addrlen;
int n;
+ const char* c;
+ char s[80];
assert(sock->type == eSOCK_ClientSide);
-#ifdef NCBI_OS_UNIX
- assert(!sock->file[0]);
-#endif /*NCBI_OS_UNIX*/
/* initialize internals */
verify(s_Initialized || SOCK_InitializeAPI() == eIO_Success);
- /* get address of the remote host (assume the same host if it is NULL) */
- x_host = host && *host ? SOCK_gethostbyname(host) : sock->host;
- if ( !x_host ) {
- CORE_LOGF(eLOG_Error, ("%s[SOCK::s_Connect] Failed "
- "SOCK_gethostbyname(\"%.64s\")",
- s_ID(sock, _id), host));
- return eIO_Unknown;
- }
-
- /* set the port to connect to (assume the same port if "port" is zero) */
- x_port = (unsigned short) (port ? htons(port) : sock->port);
+ memset(&addr, 0, sizeof(addr));
+#ifdef NCBI_OS_UNIX
+ if (sock->path[0]) {
+ addrlen = sizeof(addr.sun);
+ addr.sun.sun_family = AF_UNIX;
+ strncpy0(addr.sun.sun_path, sock->path, sizeof(addr.sun.sun_path)-1);
+ c = sock->path;
+ } else
+#endif /*NCBI_OS_UNIX*/
+ {
+ unsigned int x_host;
+ unsigned short x_port;
+ addrlen = sizeof(addr.sin);
+ addr.sin.sin_family = AF_INET;
+ /* get address of the remote host (assume the same host if NULL) */
+ x_host = host && *host ? SOCK_gethostbyname(host) : sock->host;
+ if ( !x_host ) {
+ CORE_LOGF(eLOG_Error, ("%s[SOCK::s_Connect] Failed "
+ "SOCK_gethostbyname(\"%.64s\")",
+ s_ID(sock, _id), host));
+ return eIO_Unknown;
+ }
+ addr.sin.sin_addr.s_addr = x_host;
+ /* set the port to connect to (same port if "port" is zero) */
+ x_port = (unsigned short) (port ? htons(port) : sock->port);
+ addr.sin.sin_port = x_port;
+#ifdef HAVE_SIN_LEN
+ addr.sin.sin_len = sizeof(addr.sin);
+#endif /*HAVE_SIN_LEN*/
+ sock->host = x_host;
+ sock->port = x_port;
+ c = HostPortToString(x_host,ntohs(x_port),s,sizeof(s)) ? s : "???";
+ }
- /* create new socket */
- if ((x_sock = socket(AF_INET, SOCK_STREAM, 0)) == SOCK_INVALID) {
+ /* check the new socket */
+ if ((x_sock = socket(addr.sa.sa_family, SOCK_STREAM, 0)) == SOCK_INVALID) {
int x_errno = SOCK_ERRNO;
CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
("%s[SOCK::s_Connect] Cannot create socket",
@@ -1598,18 +1798,8 @@ static EIO_Status s_Connect(SOCK sock,
return eIO_Unknown;
}
- /* fill in the server "addr" to connect to */
- memset(&peer, 0, sizeof(peer));
- peer.sin_family = AF_INET;
- peer.sin_addr.s_addr = x_host;
- peer.sin_port = x_port;
-#ifdef HAVE_SIN_LEN
- peer.sin_len = sizeof(peer);
-#endif /*HAVE_SIN_LEN*/
-
- /* statistics & logging */
if (sock->log == eOn || (sock->log == eDefault && s_Log == eOn))
- s_DoLog(sock, eIO_Open, 0, 0, (struct sockaddr*) &peer);
+ s_DoLog(sock, eIO_Open, 0, 0, &addr.sa);
/* establish connection to the peer */
sock->r_status = eIO_Success;
@@ -1617,11 +1807,10 @@ static EIO_Status s_Connect(SOCK sock,
sock->w_status = eIO_Success;
assert(sock->w_len == 0);
for (n = 0; ; n = 1) {
- if (connect(x_sock, (struct sockaddr*) &peer, sizeof(peer)) == 0) {
+ if (connect(x_sock, &addr.sa, addrlen) == 0) {
x_errno = 0;
break;
}
-
x_errno = SOCK_ERRNO;
if (x_errno != SOCK_EINTR || sock->i_on_sig == eOn ||
(sock->i_on_sig == eDefault && s_InterruptOnSignal))
@@ -1632,11 +1821,9 @@ static EIO_Status s_Connect(SOCK sock,
(n == 0 || x_errno != SOCK_EALREADY) &&
x_errno != SOCK_EWOULDBLOCK) {
if (x_errno != SOCK_EINTR) {
- char addr[80];
- HostPortToString(x_host, ntohs(x_port), addr, sizeof(addr));
CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
("%s[SOCK::s_Connect] Failed connect() "
- "to %s", s_ID(sock, _id), addr));
+ "to %s", s_ID(sock, _id), c));
}
sock->sock = SOCK_INVALID;
SOCK_CLOSE(x_sock);
@@ -1650,12 +1837,10 @@ static EIO_Status s_Connect(SOCK sock,
status = s_IsConnected(sock, s_to2tv(timeout, &tv), &x_errno, 0);
if (status != eIO_Success) {
- char addr[80];
- HostPortToString(x_host, ntohs(x_port), addr, sizeof(addr));
CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
("%s[SOCK::s_Connect] Failed pending "
- "connect() to %s (%s)", s_ID(sock, _id),
- addr, IO_StatusStr(status)));
+ "connect() to %s (%s)",
+ s_ID(sock, _id), c, IO_StatusStr(status)));
sock->sock = SOCK_INVALID;
SOCK_CLOSE(x_sock);
return status;
@@ -1667,8 +1852,6 @@ static EIO_Status s_Connect(SOCK sock,
sock->pending = 0/*connected*/;
/* success: do not change any timeouts */
- sock->host = x_host;
- sock->port = x_port;
sock->w_len = BUF_Size(sock->w_buf);
return eIO_Success;
}
@@ -1783,7 +1966,7 @@ static int s_Recv(SOCK sock,
}
-static EIO_Status s_WritePending(SOCK, const struct timeval*, int);
+static EIO_Status s_WritePending(SOCK, const struct timeval*, int, int);
/* s_Select() with stall protection: try pull incoming data from sockets.
* This method returns array of polls, "revent"s of which are always
@@ -1830,7 +2013,7 @@ static EIO_Status s_SelectStallsafe(size_t n,
if (polls[i].event == eIO_Read && polls[i].revent == eIO_Write) {
assert(n != 1);
assert(polls[i].sock->pending || polls[i].sock->w_len);
- status = s_WritePending(polls[i].sock, tv, 1/*writeable*/);
+ status = s_WritePending(polls[i].sock, tv, 1/*writeable*/, 0);
if (status != eIO_Success && status != eIO_Timeout) {
polls[i].revent = eIO_Close;
break;
@@ -1919,6 +2102,19 @@ static EIO_Status s_WipeWBuf(SOCK sock)
}
+#ifdef NCBI_OS_MSWIN
+static void s_Add(struct timeval* tv, int ms_addend)
+{
+ tv->tv_usec += (ms_addend % 1000) * 1000;
+ tv->tv_sec += ms_addend / 1000;
+ if (tv->tv_usec >= 10000000) {
+ tv->tv_sec += tv->tv_usec / 10000000;
+ tv->tv_usec %= 10000000;
+ }
+}
+#endif /*NCBI_OS_MSWIN*/
+
+
/* Write data to the socket "as is" (as many bytes at once as possible).
* Return eIO_Success if at least some bytes were written successfully.
* Otherwise (no bytes written) return an error code to indicate the problem.
@@ -1927,22 +2123,27 @@ static EIO_Status s_WipeWBuf(SOCK sock)
static EIO_Status s_Send(SOCK sock,
const void* buf,
size_t size,
- size_t* n_written)
+ size_t* n_written,
+ int/*bool*/ oob)
{
char _id[32];
+#ifdef NCBI_OS_MSWIN
+ int no_buffer_wait = 0;
+ struct timeval timeout;
+ memset(&timeout, 0, sizeof(timeout));
+#endif /*NCBI_OS_MSWIN*/
assert(size > 0 && sock->type != eSOCK_Datagram && *n_written == 0);
for (;;) { /* optionally retry if interrupted by a signal */
/* try to write */
- int x_written = send(sock->sock, (void*) buf, size, 0);
+ int x_written = send(sock->sock, (void*) buf, size, oob ? MSG_OOB : 0);
int x_errno;
if (x_written > 0) {
/* statistics & logging */
if (sock->log == eOn || (sock->log == eDefault && s_Log == eOn))
- s_DoLog(sock, eIO_Write, buf, (size_t) x_written, 0);
+ s_DoLog(sock, eIO_Write, buf, (size_t) x_written, oob? "" : 0);
sock->n_written += x_written;
-
*n_written = x_written;
sock->w_status = eIO_Success;
break/*done*/;
@@ -1950,13 +2151,35 @@ static EIO_Status s_Send(SOCK sock,
x_errno = SOCK_ERRNO;
/* don't want to handle all possible errors... let them be "unknown" */
sock->w_status = eIO_Unknown;
+ if (oob)
+ break;
/* blocked -- retry if unblocked before the timeout expires */
/* (use stall protection if specified) */
- if (x_errno == SOCK_EWOULDBLOCK || x_errno == SOCK_EAGAIN) {
+ if (x_errno == SOCK_EWOULDBLOCK || x_errno == SOCK_EAGAIN
+#ifdef NCBI_OS_MSWIN
+ || x_errno == WSAENOBUFS
+#endif /*NCBI_OS_MSWIN*/
+ ) {
EIO_Status status;
SSOCK_Poll poll;
+#ifdef NCBI_OS_MSWIN
+ if (x_errno == WSAENOBUFS) {
+ s_Add(&timeout, no_buffer_wait);
+ if (!s_Less(&timeout, sock->w_timeout))
+ return eIO_Timeout;
+ if (no_buffer_wait)
+ Sleep(no_buffer_wait);
+ if (no_buffer_wait == 0)
+ no_buffer_wait = 10;
+ else if (no_buffer_wait < 160)
+ no_buffer_wait *= 2;
+ } else {
+ no_buffer_wait = 0;
+ memset(&timeout, 0, sizeof(timeout));
+ }
+#endif /*NCBI_OS_MSWIN*/
poll.sock = sock;
poll.event = eIO_Write;
poll.revent = eIO_Open;
@@ -1995,7 +2218,7 @@ static EIO_Status s_Send(SOCK sock,
}
}
- return sock->w_status;
+ return (EIO_Status) sock->w_status;
}
@@ -2008,7 +2231,8 @@ static EIO_Status s_Send(SOCK sock,
static EIO_Status s_WriteSliced(SOCK sock,
const void* buf,
size_t size,
- size_t* n_written)
+ size_t* n_written,
+ int/*bool*/ oob)
{
/* split output buffer by slices (of size <= SOCK_WRITE_SLICE)
* before writing to the socket
@@ -2019,7 +2243,7 @@ static EIO_Status s_WriteSliced(SOCK sock,
do {
size_t n_io = size > SOCK_WRITE_SLICE ? SOCK_WRITE_SLICE : size;
size_t n_io_done = 0;
- status = s_Send(sock, (char*) buf + *n_written, n_io, &n_io_done);
+ status = s_Send(sock, (char*) buf + *n_written, n_io, &n_io_done, oob);
if (status != eIO_Success)
break;
*n_written += n_io_done;
@@ -2037,7 +2261,8 @@ static EIO_Status s_WriteSliced(SOCK sock,
static EIO_Status s_WritePending(SOCK sock,
const struct timeval* tv,
- int/*bool*/ writeable)
+ int/*bool*/ writeable,
+ int/*bool*/ oob)
{
const struct timeval* x_tv;
EIO_Status status;
@@ -2052,12 +2277,12 @@ static EIO_Status s_WritePending(SOCK sock,
char addr[80];
char _id[32];
#ifdef NCBI_OS_UNIX
- if ( sock->file[0] ) {
- size_t len = strlen(sock->file);
+ if ( sock->path[0] ) {
+ size_t len = strlen(sock->path);
int/*bool*/ trunc = len > sizeof(addr) - 3 ? 1 : 0;
sprintf(addr, "\"%s%.*s\"", trunc ? "..." : "",
(int)(trunc ? sizeof(addr) - 6 : len),
- &sock->file[trunc ? len - sizeof(addr) + 6 : 0]);
+ &sock->path[trunc ? len - sizeof(addr) + 6 : 0]);
} else
#endif /*NCBI_OS_UNIX*/
HostPortToString(sock->host, ntohs(sock->port),
@@ -2071,7 +2296,7 @@ static EIO_Status s_WritePending(SOCK sock,
}
sock->pending = 0/*connected*/;
}
- if (sock->w_len == 0 || sock->w_status == eIO_Closed)
+ if (oob || sock->w_len == 0 || sock->w_status == eIO_Closed)
return eIO_Success;
x_tv = sock->w_timeout;
@@ -2081,7 +2306,7 @@ static EIO_Status s_WritePending(SOCK sock,
char buf[4096];
size_t n_written = 0;
size_t n_write = BUF_PeekAt(sock->w_buf, off, buf, sizeof(buf));
- status = s_WriteSliced(sock, buf, n_write, &n_written);
+ status = s_WriteSliced(sock, buf, n_write, &n_written, 0);
if (status != eIO_Success)
break;
sock->w_len -= n_written;
@@ -2109,15 +2334,15 @@ static EIO_Status s_Read(SOCK sock,
*n_read = 0;
if (sock->type == eSOCK_Datagram) {
- *n_read = peek ?
- BUF_Peek(sock->r_buf, buf, size) :
- BUF_Read(sock->r_buf, buf, size);
+ *n_read = peek
+ ? BUF_Peek(sock->r_buf, buf, size)
+ : BUF_Read(sock->r_buf, buf, size);
sock->r_status = *n_read || !size ? eIO_Success : eIO_Closed;
- return sock->r_status;
+ return (EIO_Status) sock->r_status;
}
- status = s_WritePending(sock, sock->r_timeout, 0);
- if (sock->pending || !size)
+ status = s_WritePending(sock, sock->r_timeout, 0, 0);
+ if (sock->pending || !size)
return sock->pending ? status : s_Status(sock, eIO_Read);
for (;;) { /* retry if either blocked or interrupted (optional) */
@@ -2184,7 +2409,8 @@ static EIO_Status s_Read(SOCK sock,
static EIO_Status s_Write(SOCK sock,
const void* buf,
size_t size,
- size_t* n_written)
+ size_t* n_written,
+ int/*bool*/ oob)
{
EIO_Status status;
@@ -2198,7 +2424,7 @@ static EIO_Status s_Write(SOCK sock,
*n_written = size;
} else
sock->w_status = eIO_Unknown;
- return sock->w_status;
+ return (EIO_Status) sock->w_status;
}
if (sock->w_status == eIO_Closed) {
@@ -2211,14 +2437,15 @@ static EIO_Status s_Write(SOCK sock,
return eIO_Closed;
}
- if ((status = s_WritePending(sock, sock->w_timeout, 0)) != eIO_Success) {
+ status = s_WritePending(sock, sock->w_timeout, 0, oob);
+ if (status != eIO_Success) {
if (status == eIO_Timeout || status == eIO_Closed)
return status;
return size ? status : eIO_Success;
}
assert(sock->w_len == 0);
- return size ? s_WriteSliced(sock, buf, size, n_written) : eIO_Success;
+ return size ? s_WriteSliced(sock, buf, size, n_written, oob) : eIO_Success;
}
@@ -2254,7 +2481,7 @@ static EIO_Status s_Shutdown(SOCK sock,
case eIO_Write:
if (sock->w_status == eIO_Closed)
return eIO_Success; /* has been shut down already */
- if ((status = s_WritePending(sock, tv, 0)) != eIO_Success
+ if ((status = s_WritePending(sock, tv, 0, 0)) != eIO_Success
&& (!tv || tv->tv_sec || tv->tv_usec)) {
CORE_LOGF(eLOG_Warning, ("%s[SOCK::s_Shutdown] Shutting down for "
"write with some output pending (%s)",
@@ -2273,7 +2500,7 @@ static EIO_Status s_Shutdown(SOCK sock,
if (sock->r_status == eIO_Closed && sock->w_status == eIO_Closed)
return eIO_Success;
if (sock->w_status != eIO_Closed &&
- (status = s_WritePending(sock, tv, 0)) != eIO_Success
+ (status = s_WritePending(sock, tv, 0, 0)) != eIO_Success
&& (!tv || tv->tv_sec || tv->tv_usec)) {
CORE_LOGF(eLOG_Warning, ("%s[SOCK::s_Shutdown] Shutting down for "
"R/W with some output pending (%s)",
@@ -2365,7 +2592,7 @@ static EIO_Status s_Close(SOCK sock)
"back to blocking mode", s_ID(sock, _id)));
}
} else {
- status = s_WritePending(sock, sock->c_timeout, 0);
+ status = s_WritePending(sock, sock->c_timeout, 0, 0);
if (status != eIO_Success) {
CORE_LOGF(eLOG_Warning, ("%s[SOCK::s_Close] Leaving with some "
"output data pending (%s)",
@@ -2406,35 +2633,31 @@ static EIO_Status s_Close(SOCK sock)
}
-
-extern EIO_Status SOCK_Create(const char* host,
- unsigned short port,
- const STimeout* timeout,
- SOCK* sock)
-{
- return SOCK_CreateEx(host, port, timeout, sock, 0, 0, eDefault);
-}
-
-
-extern EIO_Status SOCK_CreateEx(const char* host,
- unsigned short port,
- const STimeout* timeout,
- SOCK* sock,
- const void* data,
- size_t datalen,
- ESwitch log)
+static EIO_Status s_Create(const char* host,
+ unsigned short port,
+ const STimeout* timeout,
+ SOCK* sock,
+ const void* data,
+ size_t datalen,
+ ESwitch log)
{
unsigned int x_id = ++s_ID_Counter * 1000;
+ size_t x_n = port ? 0 : strlen(host);
SOCK x_sock;
*sock = 0;
/* allocate memory for the internal socket structure */
- if (!(x_sock = (SOCK) calloc(1, sizeof(*x_sock))))
+ if (!(x_sock = (SOCK) calloc(1, sizeof(*x_sock) + x_n)))
return eIO_Unknown;
x_sock->sock = SOCK_INVALID;
x_sock->id = x_id;
x_sock->log = log;
x_sock->type = eSOCK_ClientSide;
+#ifdef NCBI_OS_UNIX
+ if (!port) {
+ strcpy(x_sock->path, host);
+ }
+#endif /*NCBI_OS_UNIX*/
/* setup the I/O data buffer properties */
BUF_SetChunkSize(&x_sock->r_buf, SOCK_BUF_CHUNK_SIZE);
@@ -2467,6 +2690,48 @@ extern EIO_Status SOCK_CreateEx(const char* host,
}
+extern EIO_Status SOCK_Create(const char* host,
+ unsigned short port,
+ const STimeout* timeout,
+ SOCK* sock)
+{
+ if (!host || !port)
+ return eIO_InvalidArg;
+ return s_Create(host, port, timeout, sock, 0, 0, eDefault);
+}
+
+
+extern EIO_Status SOCK_CreateEx(const char* host,
+ unsigned short port,
+ const STimeout* timeout,
+ SOCK* sock,
+ const void* data,
+ size_t datalen,
+ ESwitch log)
+{
+ if (!host || !port)
+ return eIO_InvalidArg;
+ return s_Create(host, port, timeout, sock, data, datalen, log);
+}
+
+
+extern EIO_Status SOCK_CreateUNIX(const char* path,
+ const STimeout* timeout,
+ SOCK* sock,
+ const void* data,
+ size_t datalen,
+ ESwitch log)
+{
+ if (!path || !*path)
+ return eIO_InvalidArg;
+#ifdef NCBI_OS_UNIX
+ return s_Create(path, 0, timeout, sock, data, datalen, log);
+#else
+ return eIO_NotSupported;
+#endif /*NCBI_OS_UNIX*/
+}
+
+
extern EIO_Status SOCK_CreateOnTop(const void* handle,
size_t handle_size,
SOCK* sock)
@@ -2587,7 +2852,7 @@ extern EIO_Status SOCK_CreateOnTopEx(const void* handle,
x_sock->host = peer.in.sin_addr.s_addr;
x_sock->port = peer.in.sin_port;
} else
- strcpy(x_sock->file, peer.un.sun_path);
+ strcpy(x_sock->path, peer.un.sun_path);
#else
x_sock->host = peer.in.sin_addr.s_addr;
x_sock->port = peer.in.sin_port;
@@ -2627,35 +2892,18 @@ extern EIO_Status SOCK_CreateOnTopEx(const void* handle,
}
-extern EIO_Status SOCK_Reconnect(SOCK sock,
- const char* host,
- unsigned short port,
- const STimeout* timeout)
+static EIO_Status s_Reconnect(SOCK sock,
+ const char* host,
+ unsigned short port,
+ const STimeout* timeout)
{
- char _id[32];
-
- if (sock->sock == eSOCK_Datagram) {
- CORE_LOGF(eLOG_Error, ("%s[SOCK::Reconnect] "
- " Datagram socket", s_ID(sock, _id)));
- assert(0);
- return eIO_InvalidArg;
- }
-
-#ifdef NCBI_OS_UNIX
- if (sock->file[0]) {
- CORE_LOGF(eLOG_Error, ("%s[SOCK::Reconnect] UNIX socket \"%s\"",
- s_ID(sock, _id), sock->file));
- assert(0);
- return eIO_InvalidArg;
- }
-#endif /*NCBI_OS_UNIX*/
-
/* close the socket if necessary */
if (sock->sock != SOCK_INVALID)
s_Close(sock);
/* special treatment for server-side socket */
if (sock->type & eSOCK_ServerSide) {
+ char _id[32];
if (!host || !*host || !port) {
CORE_LOGF(eLOG_Error, ("%s[SOCK::Reconnect] Attempt to reconnect "
"server-side socket as the client one to "
@@ -2673,6 +2921,35 @@ extern EIO_Status SOCK_Reconnect(SOCK sock,
}
+extern EIO_Status SOCK_Reconnect(SOCK sock,
+ const char* host,
+ unsigned short port,
+ const STimeout* timeout)
+{
+ char _id[32];
+
+ if (sock->sock == eSOCK_Datagram) {
+ CORE_LOGF(eLOG_Error, ("%s[SOCK::Reconnect] "
+ " Datagram socket", s_ID(sock, _id)));
+ assert(0);
+ return eIO_InvalidArg;
+ }
+ if (host && !*host)
+ host = 0;
+
+#ifdef NCBI_OS_UNIX
+ if (sock->path[0] && (host || port)) {
+ CORE_LOGF(eLOG_Error, ("%s[SOCK::Reconnect] "
+ " Cannot reconnect UNIX socket \"%s\" as INET",
+ s_ID(sock, _id), sock->path));
+ assert(0);
+ return eIO_InvalidArg;
+ }
+#endif /*NCBI_OS_UNIX*/
+ return s_Reconnect(sock, host, port, timeout);
+}
+
+
extern EIO_Status SOCK_Shutdown(SOCK sock,
EIO_Event how)
{
@@ -2793,7 +3070,7 @@ extern EIO_Status SOCK_Wait(SOCK sock,
EIO_Status status;
const struct timeval* x_tv = s_to2tv(timeout, &tv);
- if ((status = s_WritePending(sock, x_tv, 0)) != eIO_Success) {
+ if ((status = s_WritePending(sock, x_tv, 0, 0)) != eIO_Success) {
if (event == eIO_Write || sock->pending)
return status;
}
@@ -2863,7 +3140,7 @@ extern EIO_Status POLLABLE_Poll(size_t n,
const STimeout* timeout,
size_t* n_ready)
{
- return SOCK_Poll(n, (SSOCK_Poll *const) polls, timeout, n_ready);
+ return SOCK_Poll(n, (SSOCK_Poll*) polls, timeout, n_ready);
}
@@ -2974,24 +3251,22 @@ extern EIO_Status SOCK_Read(SOCK sock,
if (sock->sock != SOCK_INVALID) {
switch ( how ) {
case eIO_ReadPlain:
- status = s_Read(sock, buf, size, &x_read, 0/*false, read*/);
+ status = s_Read(sock, buf, size, &x_read, 0/*read*/);
break;
case eIO_ReadPeek:
- status = s_Read(sock, buf, size, &x_read, 1/*true, peek*/);
+ status = s_Read(sock, buf, size, &x_read, 1/*peek*/);
break;
case eIO_ReadPersist:
x_read = 0;
do {
size_t xx_read;
- status = SOCK_Read(sock, (char*) buf + (buf? x_read : 0), size,
- &xx_read, eIO_ReadPlain);
- if (status != eIO_Success)
- break;
+ status = s_Read(sock, (char*)buf + (buf ? x_read : 0),
+ size, &xx_read, 0/*read*/);
x_read += xx_read;
size -= xx_read;
- } while ( size );
+ } while (size && status == eIO_Success);
break;
default:
@@ -3015,6 +3290,75 @@ extern EIO_Status SOCK_Read(SOCK sock,
}
+extern EIO_Status SOCK_ReadLine(SOCK sock,
+ char* line,
+ size_t size,
+ size_t* n_read)
+{
+ EIO_Status status = eIO_Success;
+ int/*bool*/ cr_seen = 0/*false*/;
+ int/*bool*/ done = 0/*false*/;
+ size_t len = 0;
+
+ do {
+ size_t i;
+ char w[1024], c;
+ size_t x_size = BUF_Size(sock->r_buf);
+ char* x_buf = size - len < sizeof(w) - cr_seen ? w : line + len;
+ if (x_size == 0 || x_size > sizeof(w) - cr_seen)
+ x_size = sizeof(w) - cr_seen;
+ status = s_Read(sock, x_buf + cr_seen,
+ size ? x_size : size, &x_size, 0/*read*/);
+ if ( !x_size )
+ done = 1/*true*/;
+ else if ( cr_seen )
+ x_size++;
+ for (i = cr_seen; i < x_size; i++) {
+ char c = x_buf[i];
+ if (c == '\0' || c == '\n') {
+ cr_seen = 0/*false*/;
+ done = 1/*true*/;
+ i++;
+ break;
+ }
+ if (c == '\r') {
+ if ( !cr_seen ) {
+ cr_seen = 1/*true*/;
+ continue;
+ }
+ }
+ if ( cr_seen )
+ line[len++] = '\r';
+ if (c != '\r')
+ cr_seen = 0/*false*/;
+ if (len >= size)
+ break;
+ if (x_buf == w)
+ line[len] = c;
+ if (++len >= size)
+ break;
+ }
+ if (len >= size)
+ done = 1/*true*/;
+ if (done && cr_seen) {
+ c = '\r';
+ if (SOCK_PushBack(sock, &c, 1) != eIO_Success)
+ status = eIO_Unknown;
+ }
+ if (i < x_size
+ && SOCK_PushBack(sock, &x_buf[i], x_size - i) != eIO_Success) {
+ status = eIO_Unknown;
+ }
+ } while (!done && status == eIO_Success);
+ if (len < size)
+ line[len] = '\0';
+ if ( n_read )
+ *n_read = len;
+
+ return status;
+}
+
+
extern EIO_Status SOCK_PushBack(SOCK sock,
const void* buf,
size_t size)
@@ -3042,21 +3386,31 @@ extern EIO_Status SOCK_Write(SOCK sock,
if (sock->sock != SOCK_INVALID) {
switch ( how ) {
+ case eIO_WriteOutOfBand:
+ if (sock->type == eSOCK_Datagram) {
+ CORE_LOGF(eLOG_Error, ("%s[SOCK::Write] "
+ " OOB not supported for datagrams",
+ s_ID(sock, _id)));
+ status = eIO_NotSupported;
+ x_written = 0;
+ break;
+ }
+ /*FALLTHRU*/
+
case eIO_WritePlain:
- status = s_Write(sock, buf, size, &x_written);
+ status = s_Write(sock, buf, size, &x_written,
+ how == eIO_WriteOutOfBand ? 1 : 0);
break;
case eIO_WritePersist:
x_written = 0;
do {
size_t xx_written;
- status = SOCK_Write(sock, (char*) buf + x_written, size,
- &xx_written, eIO_WritePlain);
- if (status != eIO_Success)
- break;
+ status = s_Write(sock, (char*) buf + x_written,
+ size, &xx_written, 0);
x_written += xx_written;
size -= xx_written;
- } while ( size );
+ } while (size && status == eIO_Success);
break;
default:
@@ -3151,8 +3505,8 @@ extern char* SOCK_GetPeerAddressString(SOCK sock,
if (!buf || !buflen)
return 0;
#ifdef NCBI_OS_UNIX
- if (sock->file[0])
- strncpy0(buf, sock->file, buflen - 1);
+ if (sock->path[0])
+ strncpy0(buf, sock->path, buflen - 1);
else
#endif /*NCBI_OS_UNIX*/
HostPortToString(sock->host, ntohs(sock->port), buf, buflen);
@@ -3191,7 +3545,7 @@ extern ESwitch SOCK_SetReadOnWriteAPI(ESwitch on_off)
extern ESwitch SOCK_SetReadOnWrite(SOCK sock, ESwitch on_off)
{
if (sock->type != eSOCK_Datagram) {
- ESwitch old = sock->r_on_w;
+ ESwitch old = (ESwitch) sock->r_on_w;
sock->r_on_w = on_off;
return old;
}
@@ -3211,7 +3565,7 @@ extern ESwitch SOCK_SetInterruptOnSignalAPI(ESwitch on_off)
extern ESwitch SOCK_SetInterruptOnSignal(SOCK sock, ESwitch on_off)
{
- ESwitch old = sock->i_on_sig;
+ ESwitch old = (ESwitch) sock->i_on_sig;
sock->i_on_sig = on_off;
return old;
}
@@ -3238,6 +3592,24 @@ extern void SOCK_SetReuseAddress(SOCK sock, int/*bool*/ on_off)
}
+extern void SOCK_DisableOSSendDelay(SOCK sock, int/*bool*/ on_off)
+{
+#ifdef TCP_NODELAY
+ if (sock->sock != SOCK_INVALID) {
+ int n = (int) on_off;
+ if (setsockopt(sock->sock, IPPROTO_TCP, TCP_NODELAY, (void*)&n, sizeof(n))) {
+ int x_errno = SOCK_ERRNO;
+ char _id[32];
+ CORE_LOGF_ERRNO_EX(eLOG_Warning, x_errno, SOCK_STRERROR(x_errno),
+ ("%s[SOCK::DisableOSSendDelay] "
+ " Failed setsockopt(%sTCP_NODELAY)",
+ s_ID(sock, _id), on_off ? "" : "!"));
+ }
+ }
+#endif /*TCP_NODELAY*/
+}
+
+
extern EIO_Status DSOCK_Create(SOCK* sock)
{
return DSOCK_CreateEx(sock, eDefault);
@@ -3323,7 +3695,7 @@ extern EIO_Status DSOCK_Bind(SOCK sock, unsigned short port)
#ifdef HAVE_SIN_LEN
addr.sin_len = sizeof(addr);
#endif /*HAVE_SIN_LEN*/
- if (bind(sock->sock, (struct sockaddr*) &addr, sizeof(addr)) !=0 ) {
+ if (bind(sock->sock, (struct sockaddr*) &addr, sizeof(addr)) != 0) {
int x_errno = SOCK_ERRNO;
CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
("%s[DSOCK::Bind] Failed bind()", s_ID(sock,_id)));
@@ -3388,7 +3760,7 @@ extern EIO_Status DSOCK_Connect(SOCK sock,
if (connect(sock->sock, (struct sockaddr*) &peer, sizeof(peer)) != 0) {
char addr[80];
int x_errno = SOCK_ERRNO;
- HostPortToString(sock->host, sock->port, addr, sizeof(addr));
+ HostPortToString(sock->host, ntohs(sock->port), addr, sizeof(addr));
CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
("%s[DSOCK::Connect] Failed connect() to %s",
s_ID(sock, _id), addr));
@@ -3429,7 +3801,7 @@ extern EIO_Status DSOCK_SendMsg(SOCK sock,
}
if ( datalen ) {
- s_Write(sock, data, datalen, &x_msgsize);
+ s_Write(sock, data, datalen, &x_msgsize, 0);
verify(x_msgsize == datalen);
}
sock->eof = 1/*true - finalized message*/;
@@ -3791,6 +4163,16 @@ extern int/*bool*/ SOCK_IsServerSide(SOCK sock)
}
+extern int/*bool*/ SOCK_IsUNIX(SOCK sock)
+{
+#ifdef NCBI_OS_UNIX
+ return sock->sock != SOCK_INVALID && sock->path[0];
+#else
+ return 0/*false*/;
+#endif /*NCBI_OS_UNIX*/
+}
+
+
extern int SOCK_gethostname(char* name,
size_t namelen)
{
@@ -3894,7 +4276,7 @@ extern unsigned int SOCK_gethostbyname(const char* hostname)
}
#else /* use some variant of gethostbyname */
struct hostent* he;
-# if defined(HAVE_GETHOSTBYNAME_R)
+# ifdef HAVE_GETHOSTBYNAME_R
static const char suffix[] = "_r";
struct hostent x_he;
char x_buf[1024];
@@ -3931,7 +4313,7 @@ extern unsigned int SOCK_gethostbyname(const char* hostname)
x_errno = EINVAL;
}
-# if !defined(HAVE_GETHOSTBYNAME_R)
+# ifndef HAVE_GETHOSTBYNAME_R
CORE_UNLOCK;
# endif /*HAVE_GETHOSTBYNAME_R*/
@@ -4066,9 +4448,85 @@ extern char* SOCK_gethostbyaddr(unsigned int host,
/*
* ===========================================================================
* $Log: ncbi_socket.c,v $
+ * Revision 6.174 2005/04/25 18:48:04 lavr
+ * Touch up for preprocessor (#if def) usage consistency
+ *
+ * Revision 6.173 2005/04/19 18:14:23 lavr
+ * Fix MSWIN compilation errors (s_Send)
+ *
+ * Revision 6.172 2005/04/19 16:33:54 lavr
+ * Introduce write-wait timeouts for Windows (no buffer space situations)
+ *
+ * Revision 6.171 2005/04/06 19:37:53 lavr
+ * Use adaptive wait-off in case of MS-Win's WSAENOBUFS error on send()
+ *
+ * Revision 6.170 2005/03/11 20:01:55 lavr
+ * Document SOCK::myport byte order
+ *
+ * Revision 6.169 2005/03/11 19:59:26 lavr
+ * Introduce SOCK::myport, solely for interactive debugging purposes
+ *
+ * Revision 6.168 2005/03/08 16:46:20 lavr
+ * Fix 32/64 int/ptr discrepancy
+ *
+ * Revision 6.167 2005/03/08 16:17:26 lavr
+ * Remove an extra const qualifier
+ *
+ * Revision 6.166 2005/02/11 18:46:47 lavr
+ * Fix some network/host byte order issues with port numbers
+ *
+ * Revision 6.165 2005/01/05 17:38:25 lavr
+ * Fix assert() in s_CreateListening()
+ *
+ * Revision 6.164 2004/12/27 15:30:35 lavr
+ * Implement OOB write
+ *
+ * Revision 6.163 2004/11/15 19:34:23 lavr
+ * Speed-up/fix SOCK_Read(), SOCK_Write() and improve SOCK_ReadLine()
+ *
+ * Revision 6.162 2004/11/15 16:11:32 lavr
+ * Yet again half-fix in SOCK_ReadLine()
+ *
+ * Revision 6.161 2004/11/15 15:39:35 lavr
+ * Fix SOCK_ReadLine()
+ *
+ * Revision 6.160 2004/11/09 21:27:01 lavr
+ * SOCK_ReadLine(): cleaned-up a little
+ *
+ * Revision 6.159 2004/11/09 21:13:28 lavr
+ * +SOCK_ReadLine()
+ *
+ * Revision 6.158 2004/10/26 20:27:10 ucko
+ * Ensure that "sun" isn't defined as a macro.
+ *
+ * Revision 6.157 2004/10/26 17:47:51 lavr
+ * Store socket's host:port when connecting (fallen out during UNIX mods)
+ *
+ * Revision 6.156 2004/10/26 16:17:07 lavr
+ * Fix SOCK_IsUNIX() (preprocessor macro check reversed)
+ *
+ * Revision 6.155 2004/10/26 14:48:13 lavr
+ * Implement UNIX socket extensions to the socket API
+ *
+ * Revision 6.154 2004/10/19 23:48:54 vakatov
+ * [MSWIN] Do not check filedes against FD_SETSIZE
+ *
+ * Revision 6.153 2004/10/19 19:12:52 kans
+ * netinet/tcp.h only included if not COMP_METRO -
+ * already includes headers in library project
+ *
+ * Revision 6.152 2004/10/19 18:50:16 lavr
+ * Heed setsockopt() type mismatch for CodeWarrior
+ *
+ * Revision 6.151 2004/10/19 18:12:15 lavr
+ * Fix compilation problems with previous commit
+ *
+ * Revision 6.150 2004/10/19 18:05:44 lavr
+ * +SOCK_DisableOSSendDelay; few other minor patches
+ *
* Revision 6.149 2004/09/08 15:12:43 ucko
- * SOCK_gethostbyaddr: use getnameinfo only if EAI_SYSTEM is defined.
- * (OSF headers provide it conditionally.)
+ * SOCK_gethostbyaddr: use getnameinfo only if EAI_SYSTEM is defined
+ * (OSF headers provide it conditionally)
*
* Revision 6.148 2004/08/20 21:24:29 lavr
* Fix CORE_LOGF_ERRNO_EX() in conditional branches we never compiled :-)
diff --git a/connect/ncbi_socket.h b/connect/ncbi_socket.h
index 6e558095..cf3ff53d 100644
--- a/connect/ncbi_socket.h
+++ b/connect/ncbi_socket.h
@@ -1,7 +1,7 @@
#ifndef CONNECT___NCBI_SOCKET__H
#define CONNECT___NCBI_SOCKET__H
-/* $Id: ncbi_socket.h,v 6.50 2004/07/23 19:04:38 lavr Exp $
+/* $Id: ncbi_socket.h,v 6.54 2005/01/05 17:37:20 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -64,6 +64,7 @@
* SOCK_GetReadTimeout
* SOCK_GetWriteTimeout
* SOCK_Read (including "peek" and "persistent read")
+ * SOCK_ReadLine
* SOCK_PushBack
* SOCK_Status
* SOCK_Write
@@ -77,6 +78,7 @@
* SOCK_SetInterruptOnSignal
* SOCK_SetReuseAddressAPI
* SOCK_SetReuseAddress
+ * SOCK_DisableOSSendDelay
*
* Datagram Socket:
*
@@ -94,6 +96,7 @@
* SOCK_IsDatagram
* SOCK_IsClientSide
* SOCK_IsServerSide
+ * SOCK_IsUNIX
*
* Data logging:
*
@@ -425,6 +428,8 @@ extern NCBI_XCONNECT_EXPORT EIO_Status SOCK_CreateOnTopEx
* NOTE2: the call is applicable to stream [not datagram] sockets only.
* NOTE3: "timeout"==NULL is infinite; "timeout"=={0,0} causes no wait for
* connection to be established and to return immediately.
+ * NOTE4: UNIX sockets can only be reconnected to the same file thus both
+ * host and port have to be passed as 0s.
*/
extern NCBI_XCONNECT_EXPORT EIO_Status SOCK_Reconnect
(SOCK sock, /* [in] handle of the socket to reconnect */
@@ -624,6 +629,29 @@ extern NCBI_XCONNECT_EXPORT EIO_Status SOCK_Read
);
+/*
+ * Read a line from SOCK. A line is terminated by either '\n' or '\0'
+ * with optional preceding '\r'. Returned result is always '\0'-
+ * terminated with preceding '\r' (if any) stripped. *n_read (if 'n_read'
+ * passed non-NULL) contains the numbed of characters written into
+ * 'buf' (not counting the terminating '\0'). If 'buf', whose size is
+ * specified via 'size' parameter, is not big enough to contain the
+ * line, all 'size' bytes will be filled, with *n_read == size upon
+ * return. Note that there will be no terminating '\0' in this
+ * (and the only) case, which the caller can easily distinguish.
+ * Return code eIO_Success upon successful completion, other - upon
+ * an error. Note that *n_read must be analyzed prior to return code,
+ * because the buffer could have received some contents before
+ * the indicated error occurred (especially when connection closed).
+ */
+extern NCBI_XCONNECT_EXPORT EIO_Status SOCK_ReadLine
+(SOCK sock,
+ char* buf, /* [out] data buffer to read to */
+ size_t size, /* [in] max # of bytes to read to "buf" */
+ size_t* n_read /* [out] # of bytes read (can be NULL) */
+ );
+
+
/* Push the specified data back to the socket input queue (in the socket's
* internal read buffer). These can be any data, not necessarily the data
* previously read from the socket.
@@ -755,6 +783,21 @@ extern NCBI_XCONNECT_EXPORT ESwitch SOCK_SetReadOnWrite
);
+/* Control OS-defined send strategy by disabling/enabling TCP
+ * Nagle algorithm that packs multiple requests into a single
+ * frame and thus transferring data in fewer transactions,
+ * miminizing the network traffic and bursting the throughput.
+ * Some applications, however, may find it useful to disable this
+ * default behavior for the sake of their performance increase
+ * (like in case of short transactions otherwise held by the system
+ * to be possibly coalesced into larger chunks).
+ */
+extern NCBI_XCONNECT_EXPORT void SOCK_DisableOSSendDelay
+(SOCK sock,
+ int/*bool*/ on_off /* NB: use true to disable; false to enable */
+ );
+
+
/******************************************************************************
* Connectionless (datagram) sockets
@@ -885,6 +928,12 @@ extern NCBI_XCONNECT_EXPORT int/*bool*/ SOCK_IsClientSide(SOCK sock);
extern NCBI_XCONNECT_EXPORT int/*bool*/ SOCK_IsServerSide(SOCK sock);
+/* Return non-zero value if socket "sock" was created by LSOCK_Accept().
+ * Return zero otherwise.
+ */
+extern NCBI_XCONNECT_EXPORT int/*bool*/ SOCK_IsUNIX(SOCK sock);
+
+
/******************************************************************************
* AUXILIARY network-specific functions (added for the portability reasons)
@@ -966,6 +1015,18 @@ extern NCBI_XCONNECT_EXPORT char* SOCK_gethostbyaddr
/*
* ---------------------------------------------------------------------------
* $Log: ncbi_socket.h,v $
+ * Revision 6.54 2005/01/05 17:37:20 lavr
+ * SOCK_ReadLine() documented in details
+ *
+ * Revision 6.53 2004/11/09 21:13:00 lavr
+ * +ReadLine
+ *
+ * Revision 6.52 2004/10/26 14:46:06 lavr
+ * <ncbi_socket.h> -> <ncbi_socket_unix.h>
+ *
+ * Revision 6.51 2004/10/19 18:05:07 lavr
+ * +SOCK_DisableOSSendDelay
+ *
* Revision 6.50 2004/07/23 19:04:38 lavr
* LSOCK_CreateEx(): last parameter to become flags (bitmask)
*
diff --git a/connect/ncbi_socket_connector.c b/connect/ncbi_socket_connector.c
index c0365fb4..f78a4649 100644
--- a/connect/ncbi_socket_connector.c
+++ b/connect/ncbi_socket_connector.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_socket_connector.c,v 6.19 2003/08/25 14:42:14 lavr Exp $
+/* $Id: ncbi_socket_connector.c,v 6.20 2005/04/20 18:15:59 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -35,6 +35,7 @@
#include "ncbi_ansi_ext.h"
#include <connect/ncbi_socket_connector.h>
+#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
@@ -373,6 +374,9 @@ extern CONNECTOR SOCK_CreateConnectorOnTopEx
/*
* --------------------------------------------------------------------------
* $Log: ncbi_socket_connector.c,v $
+ * Revision 6.20 2005/04/20 18:15:59 lavr
+ * +<assert.h>
+ *
* Revision 6.19 2003/08/25 14:42:14 lavr
* Employ new k..Timeout constants -- log modification only
*
diff --git a/connect/ncbi_socket_unix.h b/connect/ncbi_socket_unix.h
new file mode 100644
index 00000000..f73d86c8
--- /dev/null
+++ b/connect/ncbi_socket_unix.h
@@ -0,0 +1,85 @@
+#ifndef CONNECT___NCBI_SOCKET_UNIX__H
+#define CONNECT___NCBI_SOCKET_UNIX__H
+
+/* $Id: ncbi_socket_unix.h,v 1.1 2004/10/26 14:44:44 lavr Exp $
+ * ===========================================================================
+ *
+ * PUBLIC DOMAIN NOTICE
+ * National Center for Biotechnology Information
+ *
+ * This software/database is a "United States Government Work" under the
+ * terms of the United States Copyright Act. It was written as part of
+ * the author's official duties as a United States Government employee and
+ * thus cannot be copyrighted. This software/database is freely available
+ * to the public for use. The National Library of Medicine and the U.S.
+ * Government have not placed any restriction on its use or reproduction.
+ *
+ * Although all reasonable efforts have been taken to ensure the accuracy
+ * and reliability of the software and data, the NLM and the U.S.
+ * Government do not and cannot warrant the performance or results that
+ * may be obtained by using this software or data. The NLM and the U.S.
+ * Government disclaim all warranties, express or implied, including
+ * warranties of performance, merchantability or fitness for any particular
+ * purpose.
+ *
+ * Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author: Anton Lavrentiev
+ *
+ * File Description:
+ * TCP/IP socket API extension for UNIX
+ *
+ */
+
+#include <connect/ncbi_socket.h>
+
+
+/** @addtogroup Sockets
+ *
+ * @{
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern NCBI_XCONNECT_EXPORT EIO_Status LSOCK_CreateUNIX
+(const char* path, /* [in] filename of the named socket to create */
+ unsigned short backlog, /* [in] maximal # of pending connections */
+ LSOCK* lsock, /* [out] handle of the created listening socket */
+ ESwitch log /* [in] whether to do logging on this socket */
+ );
+
+
+extern NCBI_XCONNECT_EXPORT EIO_Status SOCK_CreateUNIX
+(const char* file, /* [in] filename of the UNIX socket to connect to*/
+ const STimeout* timeout, /* [in] connection timeout (infinite if NULL) */
+ SOCK* sock, /* [out] handle of the created socket */
+ const void* init_data,/* [in] initial output data segment (may be NULL)*/
+ size_t init_size,/* [in] size of initial data segment (may be 0) */
+ ESwitch log /* [in] whether to do logging on this socket */
+ );
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+/* @} */
+
+
+/*
+ * ---------------------------------------------------------------------------
+ * $Log: ncbi_socket_unix.h,v $
+ * Revision 1.1 2004/10/26 14:44:44 lavr
+ * Initial revision
+ *
+ * ===========================================================================
+ */
+
+#endif /* CONNECT___NCBI_SOCKET_UNIX__H */
diff --git a/connect/ncbi_util.c b/connect/ncbi_util.c
index c52964d2..010bd7ec 100644
--- a/connect/ncbi_util.c
+++ b/connect/ncbi_util.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_util.c,v 6.31 2003/11/14 13:04:38 lavr Exp $
+/* $Id: ncbi_util.c,v 6.32 2005/04/20 18:15:42 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -30,7 +30,6 @@
*
*/
-#include "ncbi_config.h"
#include "ncbi_priv.h"
#ifndef NCBI_CXX_TOOLKIT
# include <ncbistd.h>
@@ -500,6 +499,9 @@ extern const char* CORE_GetPlatform(void)
/*
* ---------------------------------------------------------------------------
* $Log: ncbi_util.c,v $
+ * Revision 6.32 2005/04/20 18:15:42 lavr
+ * -"ncbi_config.h"
+ *
* Revision 6.31 2003/11/14 13:04:38 lavr
* Little changes in comments [no code changes]
*
diff --git a/connect/ncbibuf.c b/connect/ncbibuf.c
deleted file mode 100644
index e3f101c6..00000000
--- a/connect/ncbibuf.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* $Id: ncbibuf.c,v 6.8 2003/01/08 15:09:07 lavr Exp $
- * ==========================================================================
- *
- * PUBLIC DOMAIN NOTICE
- * National Center for Biotechnology Information
- *
- * This software/database is a "United States Government Work" under the
- * terms of the United States Copyright Act. It was written as part of
- * the author's official duties as a United States Government employee and
- * thus cannot be copyrighted. This software/database is freely available
- * to the public for use. The National Library of Medicine and the U.S.
- * Government have not placed any restriction on its use or reproduction.
- *
- * Although all reasonable efforts have been taken to ensure the accuracy
- * and reliability of the software and data, the NLM and the U.S.
- * Government do not and cannot warrant the performance or results that
- * may be obtained by using this software or data. The NLM and the U.S.
- * Government disclaim all warranties, express or implied, including
- * warranties of performance, merchantability or fitness for any particular
- * purpose.
- *
- * Please cite the author in any work or product based on this material.
- *
- * ==========================================================================
- *
- * Author: Denis Vakatov
- *
- * File Description:
- * Memory-resident FIFO storage area (to be used e.g. in I/O buffering)
- *
- * This is just a back-compatibility interface("Nlm_*") to the real
- * BUF API located in "ncbi_buffer.[ch]".
- * Unlike the "real" BUF API, this API uses:
- * a) "Nlm_" name prefix for structures, types and functions;
- * b) "Nlm_*" fixed size integer types like "Nlm_Uint4";
- * c) "Nlm_Boolean" rather than a native "int" for the boolean type;
- * d) [MSWIN] "NLM_EXTERN" rather than just "extern" to ease the compilation
- * for MSWIN DLL.
- *
- * --------------------------------------------------------------------------
- * $Log: ncbibuf.c,v $
- * Revision 6.8 2003/01/08 15:09:07 lavr
- * Fix Nlm_BUF_Destroy() to use BUF_Destroy() w/o return value
- *
- * Revision 6.7 2000/02/25 16:45:54 vakatov
- * Redesigned to really share "ncbi_*.[ch]" etc. between the C and
- * the C++ toolkits, and even to use them in a "standalone" fashion
- *
- * Revision 6.6 1999/10/12 16:40:26 vakatov
- * Deleted all test code as there is one in "test/test_ncbi_buffer.c" now
- *
- * Revision 6.5 1999/08/17 22:30:21 vakatov
- * Use "Nlm_BUF" to avoid name clash with "BUF" in "ncbi_buffer.h" when
- * compiling with MipsPro IRIX compiler
- *
- * Revision 6.4 1999/08/17 19:47:24 vakatov
- * Moved all real code from NCBIBUF to NCBI_BUFFER; the code has been cleaned
- * from the NCBI C toolkit specific types and API calls.
- * NCBIBUF module still exists for the backward compatibility -- it
- * provides old NCBI-wise interface.
- * ==========================================================================
- */
-
-
-#include <ncbibuf.h>
-
-/* ...and undefine "Nlm_BUF_*" to allow to access <ncbi_buffer.h> API */
-#undef BUF
-#undef BUF_SetChunkSize
-#undef BUF_Size
-#undef BUF_Write
-#undef BUF_Peek
-#undef BUF_Read
-#undef BUF_PushBack
-#undef BUF_Destroy
-
-/* this is the only place where both <ncbibuf.h> and <ncbi_buffer.h> can
- * be #include'd in one source module! */
-#undef NCBIBUF__H
-
-#include <connect/ncbi_buffer.h>
-
-
-NLM_EXTERN Nlm_Uint4 Nlm_BUF_SetChunkSize
-(BUF* pBuf, Nlm_Uint4 chunk_size)
-{
- return (Nlm_Uint4) BUF_SetChunkSize(pBuf, chunk_size);
-}
-
-NLM_EXTERN Nlm_Uint4 Nlm_BUF_Size
-(BUF buf)
-{
- return (Nlm_Uint4) BUF_Size(buf);
-}
-
-NLM_EXTERN Nlm_Boolean Nlm_BUF_Write
-(BUF* pBuf, const void* data, Nlm_Uint4 size)
-{
- return (Nlm_Boolean) BUF_Write(pBuf, data, size);
-}
-
-NLM_EXTERN Nlm_Boolean Nlm_BUF_PushBack
-(BUF* pBuf, const void* data, Nlm_Uint4 size)
-{
- return (Nlm_Boolean) BUF_PushBack(pBuf, data, size);
-}
-
-
-NLM_EXTERN Nlm_Uint4 Nlm_BUF_Peek
-(BUF buf, void* data, Nlm_Uint4 size)
-{
- return (Nlm_Uint4) BUF_Peek(buf, data, size);
-}
-
-
-NLM_EXTERN Nlm_Uint4 Nlm_BUF_Read
-(BUF buf, void* data, Nlm_Uint4 size)
-{
- return (Nlm_Uint4) BUF_Read(buf, data, size);
-}
-
-
-NLM_EXTERN BUF Nlm_BUF_Destroy
-(BUF buf)
-{
- BUF_Destroy(buf);
- return 0;
-}
diff --git a/connect/ncbibuf.h b/connect/ncbibuf.h
deleted file mode 100644
index 50684517..00000000
--- a/connect/ncbibuf.h
+++ /dev/null
@@ -1,149 +0,0 @@
-#ifndef NCBIBUF__H
-#define NCBIBUF__H
-
-/* $Id: ncbibuf.h,v 6.5 1999/08/17 22:30:22 vakatov Exp $
- * ==========================================================================
- *
- * PUBLIC DOMAIN NOTICE
- * National Center for Biotechnology Information
- *
- * This software/database is a "United States Government Work" under the
- * terms of the United States Copyright Act. It was written as part of
- * the author's official duties as a United States Government employee and
- * thus cannot be copyrighted. This software/database is freely available
- * to the public for use. The National Library of Medicine and the U.S.
- * Government have not placed any restriction on its use or reproduction.
- *
- * Although all reasonable efforts have been taken to ensure the accuracy
- * and reliability of the software and data, the NLM and the U.S.
- * Government do not and cannot warrant the performance or results that
- * may be obtained by using this software or data. The NLM and the U.S.
- * Government disclaim all warranties, express or implied, including
- * warranties of performance, merchantability or fitness for any particular
- * purpose.
- *
- * Please cite the author in any work or product based on this material.
- *
- * ==========================================================================
- *
- * Author: Denis Vakatov
- *
- * File Description:
- * Memory-resident FIFO storage area (to be used e.g. in I/O buffering)
- *
- * This is just a back-compatibility interface("Nlm_*") to the real
- * BUF API located in "ncbi_buffer.[ch]".
- * Unlike the "real" BUF API, this API uses:
- * a) "Nlm_" name prefix for structures, types and functions;
- * b) "Nlm_*" fixed size integer types like "Nlm_Uint4";
- * c) "Nlm_Boolean" rather than a native "int" for the boolean type;
- * d) [MSWIN] "NLM_EXTERN" rather than just "extern" to ease the compilation
- * for MSWIN DLL.
- *
- * --------------------------------------------------------------------------
- * $Log: ncbibuf.h,v $
- * Revision 6.5 1999/08/17 22:30:22 vakatov
- * Use "Nlm_BUF" to avoid name clash with "BUF" in "ncbi_buffer.h" when
- * compiling with MipsPro IRIX compiler
- *
- * Revision 6.4 1999/08/17 19:47:25 vakatov
- * Moved all real code from NCBIBUF to NCBI_BUFFER; the code has been cleaned
- * from the NCBI C toolkit specific types and API calls.
- * NCBIBUF module still exists for the backward compatibility -- it
- * provides old NCBI-wise interface.
- *
- * ==========================================================================
- */
-
-#include <ncbilcl.h>
-#include <ncbistd.h>
-
-
-#undef NLM_EXTERN
-#ifdef NLM_IMPORT
-#define NLM_EXTERN NLM_IMPORT
-#else
-#define NLM_EXTERN extern
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define BUF Nlm_BUF
-#define BUF_SetChunkSize Nlm_BUF_SetChunkSize
-#define BUF_Size Nlm_BUF_Size
-#define BUF_Write Nlm_BUF_Write
-#define BUF_Peek Nlm_BUF_Peek
-#define BUF_Read Nlm_BUF_Read
-#define BUF_PushBack Nlm_BUF_PushBack
-#define BUF_Destroy Nlm_BUF_Destroy
-
-
-/* handle of a buffer (see "ncbi_buffer.[ch]") */
-struct BUF_tag;
-typedef struct BUF_tag* BUF;
-
-
-/* Set minimal size of the buffer memory chunk.
- * Return the actually set chunk size on success; zero on error
- * NOTE: if "*pBuf" == NULL then create it
- * if "chunk_size" is passed 0 then set it to BUF_DEF_CHUNK_SIZE
- */
-NLM_EXTERN Nlm_Uint4 BUF_SetChunkSize(BUF* pBuf, Nlm_Uint4 chunk_size);
-
-
-/* Return the number of bytes stored in "buf".
- * NOTE: return 0 if "buf" == NULL
- */
-NLM_EXTERN Nlm_Uint4 BUF_Size(BUF buf);
-
-
-/* Add new data to the end of "*pBuf" (to be read last).
- * NOTE: if "*pBuf" == NULL then create it
- */
-NLM_EXTERN Nlm_Boolean BUF_Write(BUF* pBuf, const void* data, Nlm_Uint4 size);
-
-
-/* Write the data to the very beginning of "*pBuf" (to be read first).
- * NOTE: if "*pBuf" == NULL then create it
- */
-NLM_EXTERN Nlm_Boolean BUF_PushBack(BUF* pBuf,
- const void* data, Nlm_Uint4 size);
-
-
-/* Copy up to "size" bytes stored in "buf" to "data".
- * Return the # of copied bytes(can be less than "size").
- * NOTE: "buf" and "data" can be NULL; in both cases, do nothing
- * and return 0.
- */
-NLM_EXTERN Nlm_Uint4 BUF_Peek(BUF buf, void* data, Nlm_Uint4 size);
-
-
-/* Copy up to "size" bytes stored in "buf" to "data" and remove
- * copied data from the "buf".
- * Return the # of copied-and/or-removed bytes(can be less than "size")
- * NOTE: if "buf" == NULL then do nothing and return 0
- * if "data" == NULL then do not copy data anywhere(still, remove it)
- */
-NLM_EXTERN Nlm_Uint4 BUF_Read(BUF buf, void* data, Nlm_Uint4 size);
-
-
-/* Destroy all internal data; return NULL
- * NOTE: do nothing if "buf" == NULL
- */
-NLM_EXTERN BUF BUF_Destroy(BUF buf);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#undef NLM_EXTERN
-#ifdef NLM_EXPORT
-#define NLM_EXTERN NLM_EXPORT
-#else
-#define NLM_EXTERN
-#endif
-
-#endif /* NCBIBUF__H */
diff --git a/connect/ncbisock.c b/connect/ncbisock.c
deleted file mode 100644
index 954d7f00..00000000
--- a/connect/ncbisock.c
+++ /dev/null
@@ -1,535 +0,0 @@
-/* $Id: ncbisock.c,v 6.11 2002/09/13 19:17:36 lavr Exp $
- * ===========================================================================
- *
- * PUBLIC DOMAIN NOTICE
- * National Center for Biotechnology Information
- *
- * This software/database is a "United States Government Work" under the
- * terms of the United States Copyright Act. It was written as part of
- * the author's official duties as a United States Government employee and
- * thus cannot be copyrighted. This software/database is freely available
- * to the public for use. The National Library of Medicine and the U.S.
- * Government have not placed any restriction on its use or reproduction.
- *
- * Although all reasonable efforts have been taken to ensure the accuracy
- * and reliability of the software and data, the NLM and the U.S.
- * Government do not and cannot warrant the performance or results that
- * may be obtained by using this software or data. The NLM and the U.S.
- * Government disclaim all warranties, express or implied, including
- * warranties of performance, merchantability or fitness for any particular
- * purpose.
- *
- * Please cite the author in any work or product based on this material.
- *
- * ===========================================================================
- *
- * Author: Denis Vakatov
- *
- * File Description:
- * Plain portable TCP/IP socket API for: UNIX, MS-Win, MacOS
- *
- * This is just a back-compatibility interface("Nlm_*") to the real
- * SOCK API located in "ncbi_socket.[ch]".
- * Unlike the "real" SOCK API, this API uses:
- * a) "Nlm_" name prefix for structures, types and functions;
- * b) "Nlm_*" fixed size integer types like "Nlm_Uint4";
- * c) "Nlm_Boolean" rather than a native "int" for the boolean type;
- * d) [MSWIN] "NLM_EXTERN" rather than just "extern" to ease the compilation
- * for MSWIN DLL.
- *
- * ---------------------------------------------------------------------------
- * $Log: ncbisock.c,v $
- * Revision 6.11 2002/09/13 19:17:36 lavr
- * Fix incomplete S2E() mapping
- *
- * Revision 6.10 2002/08/27 20:26:23 lavr
- * Fixed reference: SOCK_htonl() -> SOCK_HostToNetLong()
- *
- * Revision 6.9 2002/08/12 20:01:30 lavr
- * Fix SOCK_Write() call (misplaced argument)
- *
- * Revision 6.8 2002/08/12 19:55:46 lavr
- * Use write_mode in SOCK_Write()
- *
- * Revision 6.7 2002/08/07 18:45:17 lavr
- * Change from deprecated to current EIO_ReadMethod enums
- *
- * Revision 6.6 2002/08/07 18:34:21 lavr
- * SOCK_GetAddress() -> SOCK_GetPeerAddress()
- *
- * Revision 6.5 2001/04/03 22:17:05 juran
- * Backout previous change.
- *
- * Revision 6.3 2000/12/07 19:16:59 vakatov
- * Use new NCBI_SOCKET API imported from the C++ Toolkit
- *
- * Revision 6.2 2000/02/25 16:45:54 vakatov
- * Redesigned to really share "ncbi_*.[ch]" etc. between the C and
- * the C++ toolkits, and even to use them in a "standalone" fashion
- *
- * Revision 6.3 2000/02/18 23:50:41 vakatov
- * REDESIGN
- *
- * Revision 6.2 2000/02/17 21:51:15 vakatov
- * REDESIGN::
- *
- * Revision 6.1 1999/10/18 15:39:05 vakatov
- * Initial revision
- * This is actually just an interface for the back compatibility with the
- * former "ncbisock.[ch]"; the real code is in "ncbi_socket.[ch]"
- * ===========================================================================
- */
-
-#include <ncbithr.h>
-#include <ncbisock.h>
-#include <ncbierr.h>
-
-
-/* Undefine some "Nlm_SOCK_*" to clear the access to <ncbi_socket.h> API
- */
-#undef LSOCK
-#undef SOCK
-
-#undef LSOCK_Create
-#undef LSOCK_Accept
-#undef LSOCK_Close
-#undef LSOCK_GetOSHandle
-
-#undef SOCK_Create
-#undef SOCK_SetTimeout
-#undef SOCK_Read
-#undef SOCK_ReadPersist
-#undef SOCK_Peek
-#undef SOCK_PushBack
-#undef SOCK_Eof
-#undef SOCK_Write
-#undef SOCK_Reconnect
-#undef SOCK_Close
-#undef SOCK_GetOSHandle
-
-
-/* This is the only place where both <ncbibuf.h> and <ncbi_buffer.h> are
- * allowed to be #include'd in the same source module!
- */
-#undef NCBISOCK__H
-
-#include <connect/ncbi_socket.h>
-#include <connect/ncbi_util.h>
-
-
-/* EIO_Status <--> ESOCK_ErrCode
- */
-static ESOCK_ErrCode s_ESOCK_ErrCode[eIO_Unknown + 1] = {
- eSOCK_ESuccess,
- eSOCK_ETimeout,
- eSOCK_EClosed,
- eSOCK_EUnknown,
- eSOCK_EUnknown,
- eSOCK_EUnknown,
- eSOCK_EUnknown
-};
-#define S2E(status) s_ESOCK_ErrCode[(int) status]
-
-static EIO_Status s_EIO_Status[eSOCK_EUnknown + 1] = {
- eIO_Success,
- eIO_Timeout,
- eIO_Closed,
- eIO_Unknown
-};
-#define E2S(err_code) s_EIO_Status[(int) err_code]
-
-
-/* ESOCK_Mode -> EIO_Event
- */
-static EIO_Event s_EIO_Event[3] = {
- eIO_Read,
- eIO_Write,
- eIO_ReadWrite
-};
-#define M2E(mode) s_EIO_Event[(int) mode]
-
-
-/***********************************************************************
- * INITIALIZATION -- to provide MT-safety and error posting
- */
-
-#if defined(__cplusplus)
-extern "C" {
- static int/*bool*/ s_MT_LOCK_Handler(void* user_data, EMT_Lock how);
- static void s_MT_LOCK_Cleanup(void* user_data);
- static void s_LOG_Handler(void* user_data, SLOG_Handler* call_data);
-}
-#endif /* __cplusplus */
-
-
-static int/*bool*/ s_MT_LOCK_Handler(void* user_data, EMT_Lock how)
-{
- TNlmRWlock rw_lock = (TNlmRWlock) user_data;
- Int4 ret_code;
- switch ( how ) {
- case eMT_Lock:
- ret_code = NlmRWwrlock(rw_lock);
- break;
- case eMT_LockRead:
- ret_code = NlmRWrdlock(rw_lock);
- break;
- case eMT_Unlock:
- ret_code = NlmRWunlock(rw_lock);
- break;
- default:
- ASSERT(0);
- ret_code = 1/*bad*/;
- }
-
- return (ret_code == 0);
-}
-
-static void s_MT_LOCK_Cleanup(void* user_data)
-{
- NlmRWdestroy((TNlmRWlock) user_data);
-}
-
-
-static void s_LOG_Handler(void* user_data, SLOG_Handler* call_data)
-{
- static ErrSev s_Lev2Sev[eLOG_Fatal + 1] = {
- SEV_INFO,
- SEV_INFO,
- SEV_WARNING,
- SEV_ERROR,
- SEV_REJECT,
- SEV_FATAL
- };
-
- if (Nlm_ErrSetContext(call_data->module, call_data->file, call_data->line,
- 0, 0, 0, 0) == 0) {
- ErrSev sev = s_Lev2Sev[(int) call_data->level];
- Nlm_ErrPostStr(sev, SOCK_ERRCODE, 0, call_data->message);
- }
-}
-
-
-static int/*bool*/ s_Initialized = 0/*false*/;
-static TNlmMutex s_InitMutex;
-
-static int/*fake*/ s_Initialize(void)
-{
- NlmMutexLockEx(&s_InitMutex);
- if ( !s_Initialized ) {
- /* MT safety */
- if ( NlmThreadsAvailable() ) {
- TNlmRWlock rw_lock = NlmRWinit();
- if ( !rw_lock ) {
- ASSERT(0);
- } else {
- MT_LOCK lk =
- MT_LOCK_Create(rw_lock, s_MT_LOCK_Handler, s_MT_LOCK_Cleanup);
- ASSERT(lk);
- CORE_SetLOCK(lk);
- }
- }
-
- /* Error posting */
- CORE_SetLOG( LOG_Create(0, s_LOG_Handler, 0, 0) );
-
- /* API initialization */
- {{
- if (SOCK_InitializeAPI() == eIO_Success)
- s_Initialized = 1/*true*/;
- else
- ASSERT(0);
- }}
- }
- NlmMutexUnlock(s_InitMutex);
- return 1;
-}
-
-#define INITIALIZE (void)(s_Initialized ? 1 : s_Initialize())
-
-
-
-/******************************************************************************
- * SHUTDOWN
- */
-
-NLM_EXTERN ESOCK_ErrCode SOCK_Destroy
-(void)
-{
- ESOCK_ErrCode err_code;
- TNlmMutex x_InitMutex;
-
- NlmMutexLockEx(&s_InitMutex);
-
- if ( s_Initialized ) {
- err_code = S2E( SOCK_ShutdownAPI() );
- s_Initialized = 0/*false*/;
- } else {
- err_code = eSOCK_ESuccess;
- }
-
- x_InitMutex = s_InitMutex;
- s_InitMutex = 0;
- NlmMutexUnlock(x_InitMutex);
- NlmMutexDestroy(x_InitMutex);
-
- return err_code;
-}
-
-
-
-/***********************************************************************
- * MISC
- */
-
-NLM_EXTERN const char* SOCK_ErrCodeStr
-(ESOCK_ErrCode err_code)
-{
- return IO_StatusStr( E2S(err_code) );
-}
-
-
-
-/***********************************************************************
- * LSOCK
- */
-
-NLM_EXTERN ESOCK_ErrCode Nlm_LSOCK_Create
-(Nlm_Uint2 port,
- Nlm_Uint2 n_listen,
- LSOCK* lsock)
-{
- INITIALIZE;
- return S2E( LSOCK_Create(port, n_listen, lsock) );
-}
-
-
-NLM_EXTERN ESOCK_ErrCode Nlm_LSOCK_Accept
-(LSOCK lsock,
- const STimeout* timeout,
- SOCK* sock)
-{
- return S2E( LSOCK_Accept(lsock, timeout, sock) );
-}
-
-
-NLM_EXTERN ESOCK_ErrCode Nlm_LSOCK_Close
-(LSOCK lsock)
-{
- return S2E( LSOCK_Close(lsock) );
-}
-
-
-NLM_EXTERN ESOCK_ErrCode Nlm_LSOCK_GetOSHandle
-(LSOCK lsock,
- void* handle_buf,
- Nlm_Uint4 handle_size)
-{
- return S2E( LSOCK_GetOSHandle(lsock, handle_buf, (size_t) handle_size) );
-}
-
-
-
-/***********************************************************************
- * SOCK
- */
-
-NLM_EXTERN ESOCK_ErrCode Nlm_SOCK_Create
-(const char* host,
- Nlm_Uint2 port,
- const STimeout* timeout,
- SOCK* sock)
-{
- INITIALIZE;
- return S2E( SOCK_Create(host, port, timeout, sock) );
-}
-
-
-NLM_EXTERN ESOCK_ErrCode Nlm_SOCK_Reconnect
-(SOCK sock,
- const char* host,
- Nlm_Uint2 port,
- const STimeout* timeout)
-{
- return S2E( SOCK_Reconnect(sock, host, port, timeout) );
-}
-
-
-NLM_EXTERN ESOCK_ErrCode Nlm_SOCK_Close
-(SOCK sock)
-{
- return S2E( SOCK_Close(sock) );
-}
-
-
-NLM_EXTERN ESOCK_ErrCode Nlm_SOCK_Select
-(SOCK sock,
- Nlm_ESOCK_Mode mode,
- const STimeout* timeout)
-{
- return S2E( SOCK_Wait(sock, M2E(mode), timeout) );
-}
-
-
-NLM_EXTERN ESOCK_ErrCode Nlm_SOCK_SetTimeout
-(SOCK sock,
- Nlm_ESOCK_Mode mode,
- const STimeout* new_timeout,
- STimeout* r_timeout,
- STimeout* w_timeout)
-{
- /* retrieve R and/or W timeouts, if requested */
- static const STimeout s_Infinite = { 99999999, 999999 };
- if ( r_timeout ) {
- const STimeout* x_timeout = SOCK_GetTimeout(sock, eIO_Read);
- *r_timeout = x_timeout ? *x_timeout : s_Infinite;
- }
- if ( w_timeout ) {
- const STimeout* x_timeout = SOCK_GetTimeout(sock, eIO_Write);
- *w_timeout = x_timeout ? *x_timeout : s_Infinite;
- }
-
- /* special case -- do not change the timeout(s) */
- if (new_timeout == SOCK_GET_TIMEOUT)
- return Nlm_eSOCK_Success;
-
- /* change C(close) timeout when W timeout is changed */
- if (mode == eSOCK_OnWrite || mode == eSOCK_OnReadWrite) {
- VERIFY(SOCK_SetTimeout(sock, eIO_Close, new_timeout) == eIO_Success);
- }
-
- /* change R and/or W timeouts */
- return S2E( SOCK_SetTimeout(sock, M2E(mode), new_timeout) );
-}
-
-
-NLM_EXTERN ESOCK_ErrCode Nlm_SOCK_Read
-(SOCK sock,
- void* buf,
- Nlm_Uint4 size,
- Nlm_Uint4* n_read)
-{
- size_t x_read;
- ESOCK_ErrCode err_code =
- S2E( SOCK_Read(sock, buf, (size_t) size, &x_read, eIO_ReadPlain) );
- *n_read = (Nlm_Uint4) x_read;
- return err_code;
-}
-
-
-NLM_EXTERN ESOCK_ErrCode Nlm_SOCK_ReadPersist
-(SOCK sock,
- void* buf,
- Nlm_Uint4 size,
- Nlm_Uint4* n_read)
-{
- size_t x_read;
- ESOCK_ErrCode err_code =
- S2E( SOCK_Read(sock, buf, (size_t) size, &x_read, eIO_ReadPersist) );
- *n_read = (Nlm_Uint4) x_read;
- return err_code;
-}
-
-
-NLM_EXTERN ESOCK_ErrCode Nlm_SOCK_Peek
-(SOCK sock,
- void* buf,
- Nlm_Uint4 size,
- Nlm_Uint4* n_read)
-{
- size_t x_read;
- ESOCK_ErrCode err_code =
- S2E( SOCK_Read(sock, buf, (size_t) size, &x_read, eIO_ReadPeek) );
- *n_read = (Nlm_Uint4) x_read;
- return err_code;
-}
-
-
-NLM_EXTERN ESOCK_ErrCode Nlm_SOCK_PushBack
-(SOCK sock,
- const void* buf,
- Nlm_Uint4 size)
-{
- return S2E( SOCK_PushBack(sock, buf, (size_t) size) );
-}
-
-
-NLM_EXTERN Nlm_Boolean Nlm_SOCK_Eof(SOCK sock)
-{
- return (SOCK_Status(sock, eIO_Read) == eIO_Closed);
-}
-
-
-NLM_EXTERN ESOCK_ErrCode Nlm_SOCK_Write
-(SOCK sock,
- const void* buf,
- Nlm_Uint4 size,
- Nlm_Uint4* n_written)
-{
- size_t x_written;
- ESOCK_ErrCode err_code =
- S2E( SOCK_Write(sock, buf, (size_t) size, &x_written, eIO_WritePersist) );
- if ( n_written )
- *n_written = (Nlm_Uint4) x_written;
- return err_code;
-}
-
-
-NLM_EXTERN void Nlm_SOCK_Address
-(SOCK sock,
- Nlm_Uint4* host,
- Nlm_Uint2* port,
- Nlm_Boolean network_byte_order)
-{
- if ( host ) {
- unsigned int x_host;
- SOCK_GetPeerAddress(sock, &x_host, 0, network_byte_order
- ? eNH_NetworkByteOrder : eNH_HostByteOrder);
- *host = x_host;
- }
- if ( port ) {
- unsigned short x_port;
- SOCK_GetPeerAddress(sock, 0, &x_port, network_byte_order
- ? eNH_NetworkByteOrder : eNH_HostByteOrder);
- *port = x_port;
- }
-}
-
-
-NLM_EXTERN ESOCK_ErrCode Nlm_SOCK_GetOSHandle
-(SOCK sock,
- void* handle_buf,
- Nlm_Uint4 handle_size)
-{
- return S2E( SOCK_GetOSHandle(sock, handle_buf, (size_t) handle_size) );
-}
-
-
-
-/***********************************************************************
- * AUXILIARY
- */
-
-NLM_EXTERN Nlm_Boolean Nlm_GetHostName
-(char* name,
- Nlm_Uint4 namelen)
-{
- INITIALIZE;
- return SOCK_gethostname(name, (size_t) namelen) ? FALSE : TRUE;
-}
-
-
-NLM_EXTERN Nlm_Boolean Nlm_Uint4toInaddr
-(Nlm_Uint4 ui4_addr,
- char* buf,
- Nlm_Uint4 buf_len)
-{
- INITIALIZE;
- return SOCK_ntoa((unsigned int) ui4_addr, buf, (size_t) buf_len) ?
- FALSE : TRUE;
-}
-
-
-NLM_EXTERN Nlm_Uint4 Nlm_htonl(Nlm_Uint4 value)
-{
- return (Nlm_Uint4) SOCK_HostToNetLong((Nlm_Uint4) value);
-}
diff --git a/connect/ncbisock.h b/connect/ncbisock.h
deleted file mode 100644
index 68091266..00000000
--- a/connect/ncbisock.h
+++ /dev/null
@@ -1,412 +0,0 @@
-#ifndef NCBISOCK__H
-#define NCBISOCK__H
-
-/* $Id: ncbisock.h,v 6.3 2004/04/01 13:43:06 lavr Exp $
- * ===========================================================================
- *
- * PUBLIC DOMAIN NOTICE
- * National Center for Biotechnology Information
- *
- * This software/database is a "United States Government Work" under the
- * terms of the United States Copyright Act. It was written as part of
- * the author's official duties as a United States Government employee and
- * thus cannot be copyrighted. This software/database is freely available
- * to the public for use. The National Library of Medicine and the U.S.
- * Government have not placed any restriction on its use or reproduction.
- *
- * Although all reasonable efforts have been taken to ensure the accuracy
- * and reliability of the software and data, the NLM and the U.S.
- * Government do not and cannot warrant the performance or results that
- * may be obtained by using this software or data. The NLM and the U.S.
- * Government disclaim all warranties, express or implied, including
- * warranties of performance, merchantability or fitness for any particular
- * purpose.
- *
- * Please cite the author in any work or product based on this material.
- *
- * ===========================================================================
- *
- * Author: Denis Vakatov
- *
- * File Description:
- * Plain portable TCP/IP socket API for: UNIX, MS-Win, MacOS
- *
- * This is just a back-compatibility interface("Nlm_*") to the real
- * SOCK API located in "ncbi_socket.[ch]".
- * Unlike the "real" SOCK API, this API uses:
- * a) "Nlm_" name prefix for structures, types and functions;
- * b) "Nlm_*" fixed size integer types like "Nlm_Uint4";
- * c) "Nlm_Boolean" rather than a native "int" for the boolean type;
- * d) [MSWIN] "NLM_EXTERN" rather than just "extern" to ease the compilation
- * for MSWIN DLL.
- *
- * ---------------------------------------------------------------------------
- * $Log: ncbisock.h,v $
- * Revision 6.3 2004/04/01 13:43:06 lavr
- * Spell "occurred", "occurrence", and "occurring"
- *
- * Revision 6.2 2000/02/25 16:45:55 vakatov
- * Redesigned to really share "ncbi_*.[ch]" etc. between the C and
- * the C++ toolkits, and even to use them in a "standalone" fashion
- *
- * Revision 6.3 2000/02/17 21:51:34 vakatov
- * REDESIGN::
- *
- * Revision 6.2 2000/02/17 19:37:42 vakatov
- * REDESIGN::
- *
- * Revision 6.1 1999/10/18 15:39:05 vakatov
- * Initial revision
- * This is actually just an interface for the back compatibility with the
- * former "ncbisock.[ch]"; the real code is in "ncbi_socket.[ch]"
- * ===========================================================================
- */
-
-#include <ncbistd.h>
-
-
-#define LSOCK Nlm_LSOCK
-#define SOCK Nlm_SOCK
-
-#define ESOCK_ErrCode Nlm_ESOCK_ErrCode
-#define eSOCK_ESuccess Nlm_eSOCK_Success
-#define eSOCK_ETimeout Nlm_eSOCK_Timeout
-#define eSOCK_EClosed Nlm_eSOCK_Closed
-#define eSOCK_EUnknown Nlm_eSOCK_Unknown
-
-#define ESOCK_Mode Nlm_ESOCK_Mode
-#define eSOCK_OnRead Nlm_eSOCK_OnRead
-#define eSOCK_OnWrite Nlm_eSOCK_OnWrite
-#define eSOCK_OnReadWrite Nlm_eSOCK_OnReadWrite
-
-#define SOCK_ErrCodeStr Nlm_SOCK_ErrCodeStr
-
-#define SOCK_Initialize Nlm_SOCK_Initialize
-#define SOCK_Destroy Nlm_SOCK_Destroy
-
-#define LSOCK_Create Nlm_LSOCK_Create
-#define LSOCK_Accept Nlm_LSOCK_Accept
-#define LSOCK_Close Nlm_LSOCK_Close
-#define LSOCK_GetOSHandle Nlm_LSOCK_GetOSHandle
-
-#define SOCK_Create Nlm_SOCK_Create
-#define SOCK_SetTimeout Nlm_SOCK_SetTimeout
-#define SOCK_Select Nlm_SOCK_Select
-#define SOCK_Read Nlm_SOCK_Read
-#define SOCK_ReadPersist Nlm_SOCK_ReadPersist
-#define SOCK_Peek Nlm_SOCK_Peek
-#define SOCK_PushBack Nlm_SOCK_PushBack
-#define SOCK_Eof Nlm_SOCK_Eof
-#define SOCK_Write Nlm_SOCK_Write
-#define SOCK_Address Nlm_SOCK_Address
-#define SOCK_Reconnect Nlm_SOCK_Reconnect
-#define SOCK_Close Nlm_SOCK_Close
-#define SOCK_GetOSHandle Nlm_SOCK_GetOSHandle
-
-#define GetHostName Nlm_GetHostName
-#define Uint4toInaddr Nlm_Uint4toInaddr
-
-/* for ErrPost */
-#define SOCK_ERRCODE 777
-
-
-#undef NLM_EXTERN
-#ifdef NLM_IMPORT
-#define NLM_EXTERN NLM_IMPORT
-#else
-#define NLM_EXTERN extern
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* Handle of a socket (see "ncbi_socket.[ch]")
- */
-struct LSOCK_tag; /* listening socket: internal storage */
-typedef struct LSOCK_tag* LSOCK; /* listening socket: handle */
-
-struct SOCK_tag; /* socket: internal storage */
-typedef struct SOCK_tag* SOCK; /* socket: handle */
-
-
-/* Error code
- */
-typedef enum
-{
- eSOCK_ESuccess = 0, /* everything is fine, no errors occurred */
- eSOCK_ETimeout, /* timeout expired before the data could be i/o'd */
- eSOCK_EClosed, /* peer has closed the connection */
-
- eSOCK_EUnknown /* unknown(most probably -- fatal) error */
-} ESOCK_ErrCode;
-
-
-/* I/O direction
- */
-typedef enum {
- eSOCK_OnRead,
- eSOCK_OnWrite,
- eSOCK_OnReadWrite
-} ESOCK_Mode;
-
-
-/* Return (const) verbal description for the passed error code
- */
-NLM_EXTERN const char* SOCK_ErrCodeStr
-(ESOCK_ErrCode err_code
- );
-
-
-
-/******************************************************************************
- * LISTENING SOCKET
- */
-
-
-/* [SERVER-side] Create and initialize the server-side(listening) socket
- * (socket() + bind() + listen())
- */
-NLM_EXTERN ESOCK_ErrCode LSOCK_Create
-(Nlm_Uint2 port, /* [in] the port to listen at */
- Nlm_Uint2 n_listen, /* [in] maximal # of pending connections */
- LSOCK* lsock /* [out] handle of the created listening socket */
- );
-
-
-/* [SERVER-side] Accept connection from a client
- * NOTE: the "*timeout" is for this accept() only; to set i/o timeout,
- * use SOCK_Timeout(); (by default -- infinite)
- */
-NLM_EXTERN ESOCK_ErrCode LSOCK_Accept
-(LSOCK lsock, /* [in] handle of a listening socket */
- const STimeout* timeout, /* [in] timeout(infinite if NULL) */
- SOCK* sock /* [out] handle of the created socket */
- );
-
-
-/* [SERVER-side] Close the listening socket, destroy relevant internal data
- */
-NLM_EXTERN ESOCK_ErrCode LSOCK_Close
-(LSOCK lsock
- );
-
-
-/* Get an OS-dependent native socket handle to use by platform-specific API.
- * FYI: on MS-Windows it will be "SOCKET", on other platforms -- "int".
- */
-NLM_EXTERN ESOCK_ErrCode LSOCK_GetOSHandle
-(LSOCK lsock,
- void* handle_buf, /* pointer to a memory area to put the OS handle at */
- Nlm_Uint4 handle_size /* exact(!) size of the expected OS handle */
- );
-
-
-
-/******************************************************************************
- * SOCKET
- */
-
-
-/* [CLIENT-side] Connect client to another(server-side, listening) socket
- * (socket() + connect() [+ select()])
- */
-NLM_EXTERN ESOCK_ErrCode SOCK_Create
-(const char* host, /* [in] server host */
- Nlm_Uint2 port, /* [in] server port */
- const STimeout* timeout, /* [in] the connect timeout */
- SOCK* sock /* [out] handle of the created socket */
-);
-
-
-/* [CLIENT-side] Close the socket referred by "sock" and then connect
- * it to another "host:port"; fail if it takes more than "timeout".
- * (close() + connect() [+ select()])
- *
- * HINT: if "host" is NULL then connect to the same host address as before
- * if "port" is zero then connect to the same port # as before
- * NOTE: "new" socket inherits the i/o timeouts,
- */
-NLM_EXTERN ESOCK_ErrCode SOCK_Reconnect
-(SOCK sock, /* handle of the socket to reconnect */
- const char* host, /* [in] server host */
- Nlm_Uint2 port, /* [in] server port */
- const STimeout* timeout /* [in] the connect timeout */
- );
-
-
-/* [CLIENT-side] Close the connection, destroy relevant internal data
- * NOTE: if write timeout is specified then it is lingering until either all
- * unsent data are sent or until the timeout expires
- * NOTE: whatever error code is returned, this function cannot be
- * called more than once for the same socket
- */
-NLM_EXTERN ESOCK_ErrCode SOCK_Close
-(SOCK sock
- );
-
-
-/* Block on the socket until either read/write(dep. on "mode") is
- * available or timeout expires(if "timeout" is NULL then assume it infinite)
- */
-NLM_EXTERN ESOCK_ErrCode SOCK_Select
-(SOCK sock,
- ESOCK_Mode mode,
- const STimeout* timeout
- );
-
-
-/* Specify timeout for the connection i/o (see SOCK_[Read|Write|Close] funcs).
- * NOTE: set the timeout to the maximum if "new_timeout" is NULL
- * NOTE: the default timeout is the maximum possible(wait "ad infinitum")
- */
-#define SOCK_GET_TIMEOUT ((const STimeout*)~0)
-NLM_EXTERN ESOCK_ErrCode SOCK_SetTimeout
-(SOCK sock,
- ESOCK_Mode mode,
- const STimeout* new_timeout, /* (dont set if equal to SOCK_GET_TIMEOUT) */
- STimeout* r_timeout, /* if non-NULL, return previous read */
- STimeout* w_timeout /* and(or) write timeout values */
- );
-
-
-/* Read up to "size" bytes from "sock" to the mem.buffer pointed by "buf".
- * In "*n_read", return the number of succesfully read bytes.
- * If there is no data available to read and the timeout(see
- * SOCK_Timeout()) is expired then return eSOCK_ETimeout.
- * NOTE: Theoretically, eSOCK_Closed may indicate an empty message
- * rather than a real closure of the connection...
- */
-NLM_EXTERN ESOCK_ErrCode SOCK_Read
-(SOCK sock,
- void* buf,
- Nlm_Uint4 size,
- Nlm_Uint4* n_read
- );
-
-
-/* Operate just like SOCK_Read() but it persistently tries to read *exactly*
- * "size" bytes, and it reads again and again -- until timeout expiration or
- * error
- */
-NLM_EXTERN ESOCK_ErrCode SOCK_ReadPersist
-(SOCK sock,
- void* buf,
- Nlm_Uint4 size,
- Nlm_Uint4* n_read
- );
-
-
-/* Operate just like SOCK_Read() but dont remove the read data from the
- * input queue.
- */
-NLM_EXTERN ESOCK_ErrCode SOCK_Peek
-(SOCK sock,
- void* buf,
- Nlm_Uint4 size,
- Nlm_Uint4* n_read
- );
-
-
-/* Push the specified data back to the socket input queue(to the socket's
- * internal read buffer). These can be any data, not necessarily the data
- * previously read from the socket.
- */
-NLM_EXTERN ESOCK_ErrCode SOCK_PushBack
-(SOCK sock,
- const void* buf,
- Nlm_Uint4 size
- );
-
-
-/* If the last input operation (Read, ReadPersist or Peek) hit EOF.
- * NOTE: the input operations does not return SOCK_eClosed unless there
- * is no more data to read/peek; thus, in the case of Peek, this is
- * the only "non-destructive" way to check whether it already hit
- * the EOF or we can still expect more data to come.
- */
-NLM_EXTERN Nlm_Boolean SOCK_Eof
-(SOCK sock
- );
-
-
-/* Write "size" bytes from the mem.buffer "buf" to "sock".
- * In "*n_written", return the number of successfully written bytes.
- * If cannot write all data and the timeout(see SOCK_Timeout()) is expired
- * then return eSOCK_ETimeout.
- */
-NLM_EXTERN ESOCK_ErrCode SOCK_Write
-(SOCK sock,
- const void* buf,
- Nlm_Uint4 size,
- Nlm_Uint4* n_written
- );
-
-
-/* Get host address and port of the socket peer
- * If "network_byte_order" is true then return them in the network byte order
- * NOTE: "host" or "port" can be NULL
- */
-NLM_EXTERN void SOCK_Address
-(SOCK sock,
- Nlm_Uint4* host,
- Nlm_Uint2* port,
- Nlm_Boolean network_byte_order
- );
-
-
-/* Get an OS-dependent native socket handle to use by platform-specific API.
- * FYI: on MS-Windows it will be "SOCKET", on other platforms -- "int".
- */
-NLM_EXTERN ESOCK_ErrCode SOCK_GetOSHandle
-(SOCK sock,
- void* handle_buf, /* pointer to a memory area to put the OS handle at */
- Nlm_Uint4 handle_size /* exact(!) size of the expected OS handle */
- );
-
-
-
-/******************************************************************************
- * SHUTDOWN
- */
-
-/* Destroy internal data used by this module
- * NOTE: no function from this API can be used after the call to SOCK_Destroy
- */
-NLM_EXTERN ESOCK_ErrCode SOCK_Destroy(void);
-
-
-
-/******************************************************************************
- * AUXILIARY network-specific functions (added for the portability reasons)
- */
-
-
-NLM_EXTERN Nlm_Boolean GetHostName
-(char* name,
- Nlm_Uint4 namelen
- );
-
-NLM_EXTERN Nlm_Boolean Uint4toInaddr
-(Nlm_Uint4 ui4_addr, /* NOTE: must be in the network byte-order */
- char* buf, /* to be filled by smth. like "123.45.67.89\0" */
- Nlm_Uint4 buf_len
- );
-
-/* Total KLUDGE (dont use this beast, please) */
-NLM_EXTERN Nlm_Uint4 Nlm_htonl(Nlm_Uint4 value);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#undef NLM_EXTERN
-#ifdef NLM_EXPORT
-#define NLM_EXTERN NLM_EXPORT
-#else
-#define NLM_EXTERN
-#endif
-
-#endif /* NCBISOCK__H */
diff --git a/connect/test/http_connector_hit.c b/connect/test/http_connector_hit.c
index 713809d8..b4625f80 100644
--- a/connect/test/http_connector_hit.c
+++ b/connect/test/http_connector_hit.c
@@ -1,4 +1,4 @@
-/* $Id: http_connector_hit.c,v 6.13 2004/04/01 14:14:02 lavr Exp $
+/* $Id: http_connector_hit.c,v 6.16 2005/04/20 18:23:11 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -31,6 +31,7 @@
*/
#include "../ncbi_ansi_ext.h"
+#include "../ncbi_assert.h"
#include <connect/ncbi_http_connector.h>
#include <connect/ncbi_util.h>
/* This header must go last */
@@ -130,8 +131,8 @@ int main(int argc, const char* argv[])
if (argc < 4) {
fprintf(stderr,
"Usage: %s host port path [args] [inp_file] [user_header]\n"
- "Example: %s yar.ncbi.nlm.nih.gov 6224 "
- "/tools/vakatov/con_url.cgi 'arg1+arg2+arg3'\n",
+ "Example: %s www.ncbi.nlm.nih.gov 80 "
+ "/Service/bounce.cgi 'arg1+arg2+arg3'\n",
argv[0], argv[0]);
fprintf(stderr, "Too few arguments.\n");
return 1;
@@ -199,6 +200,15 @@ int main(int argc, const char* argv[])
/*
* --------------------------------------------------------------------------
* $Log: http_connector_hit.c,v $
+ * Revision 6.16 2005/04/20 18:23:11 lavr
+ * +"../ncbi_assert.h"
+ *
+ * Revision 6.15 2004/11/23 15:04:26 lavr
+ * Use public bounce.cgi from "www"
+ *
+ * Revision 6.14 2004/11/22 20:24:53 lavr
+ * "yar" replaced with "graceland"
+ *
* Revision 6.13 2004/04/01 14:14:02 lavr
* Spell "occurred", "occurrence", and "occurring"
*
diff --git a/connect/test/socket_io_bouncer.c b/connect/test/socket_io_bouncer.c
index 8ba1edb0..9139fe85 100644
--- a/connect/test/socket_io_bouncer.c
+++ b/connect/test/socket_io_bouncer.c
@@ -1,4 +1,4 @@
-/* $Id: socket_io_bouncer.c,v 6.7 2002/12/04 19:50:31 lavr Exp $
+/* $Id: socket_io_bouncer.c,v 6.8 2005/04/20 18:23:11 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -32,6 +32,7 @@
*/
#include "../ncbi_ansi_ext.h"
+#include "../ncbi_assert.h"
#include <connect/ncbi_socket.h>
#include <stdio.h>
#include <stdlib.h>
@@ -157,6 +158,9 @@ int main(int argc, const char* argv[])
/*
* --------------------------------------------------------------------------
* $Log: socket_io_bouncer.c,v $
+ * Revision 6.8 2005/04/20 18:23:11 lavr
+ * +"../ncbi_assert.h"
+ *
* Revision 6.7 2002/12/04 19:50:31 lavr
* #include "../ncbi_ansi_ext.h" instead of <string.h> to define strcasecmp()
*
diff --git a/connect/test/test_assert.h b/connect/test/test_assert.h
index 926f0a7c..8fc5f0bb 100644
--- a/connect/test/test_assert.h
+++ b/connect/test/test_assert.h
@@ -1,7 +1,7 @@
#ifndef TEST_ASSERT__H
#define TEST_ASSERT__H
-/* $Id: test_assert.h,v 6.22 2004/06/10 19:20:27 ivanov Exp $
+/* $Id: test_assert.h,v 6.25 2005/04/07 16:27:30 ivanov Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -57,24 +57,36 @@
* and in debug libraries, as well as all General Protection Fault messages.
* Environment variable DIAG_SILENT_ABORT must be set to "Y" or "y".
*/
+
+/* Handler for "Unhandled" exceptions */
+static LONG CALLBACK _SEH_Handler(EXCEPTION_POINTERS* ep)
+{
+ /* Always terminate a program */
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
static int _SuppressDiagPopupMessages(void)
{
/* Check environment variable for silent abort app at error */
const char* value = getenv("DIAG_SILENT_ABORT");
if (value && (*value == 'Y' || *value == 'y')) {
/* Windows GPF errors */
- SetErrorMode(SEM_NOGPFAULTERRORBOX);
+ SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
+ SEM_NOOPENFILEERRORBOX);
/* Runtime library */
_set_error_mode(_OUT_TO_STDERR);
/* Debug library */
- _CrtSetReportFile(_CRT_WARN, stderr);
+ _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_ERROR, stderr);
+ _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_ASSERT, stderr);
+ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
+
+ /* Exceptions */
+ SetUnhandledExceptionFilter(_SEH_Handler);
}
return 0;
}
@@ -130,6 +142,15 @@ static int (*_SDPM)(void) = _SuppressDiagPopupMessages;
/*
* --------------------------------------------------------------------------
* $Log: test_assert.h,v $
+ * Revision 6.25 2005/04/07 16:27:30 ivanov
+ * _SuppressDiagPopupMessages(): added handling of "Unhandled" exceptions
+ *
+ * Revision 6.24 2005/02/22 19:49:55 ivanov
+ * Added more suppress modes for SetErrorMode()
+ *
+ * Revision 6.23 2004/12/21 03:44:42 lavr
+ * Fix CRT report file destination, _CRTDBG_FILE_STDERR not stderr!
+ *
* Revision 6.22 2004/06/10 19:20:27 ivanov
* _SuppressDiagPopupMessages() returns 'int' to avoid runtime errors on MSVC7
*
diff --git a/connect/test/test_ncbi_connutil_misc.c b/connect/test/test_ncbi_connutil_misc.c
index a26809f6..732ceee0 100644
--- a/connect/test/test_ncbi_connutil_misc.c
+++ b/connect/test/test_ncbi_connutil_misc.c
@@ -1,4 +1,4 @@
-/* $Id: test_ncbi_connutil_misc.c,v 6.14 2004/04/01 14:14:02 lavr Exp $
+/* $Id: test_ncbi_connutil_misc.c,v 6.18 2005/04/20 18:23:26 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -32,6 +32,7 @@
#include <connect/ncbi_connutil.h>
#include <connect/ncbi_util.h>
+#include <stdlib.h>
#include <string.h>
/* This header must go last */
#include "test_assert.h"
@@ -141,6 +142,51 @@ static void TEST_URL_Encoding(void)
}
+/***********************************************************************
+ * TEST: BASE64_Encode(), BAS64_Decode()
+ */
+
+static void TEST_BASE64_Encoding(void)
+{
+ const char test_string[] = "Quick brown fox jumps over the lazy dog";
+ char buf1[1024], buf2[1024], buf3[1024];
+ size_t read, written, len = 16, i, j;
+
+ BASE64_Encode(test_string, strlen(test_string) + 1, &read,
+ buf1, sizeof(buf1), &written, &len);
+ assert(read == strlen(test_string) + 1);
+ assert(written < sizeof(buf1));
+ assert(buf1[written] == '\0');
+
+ assert(BASE64_Decode(buf1, written, &read,
+ buf2, sizeof(buf2), &written));
+ assert(strlen(buf1) == read);
+ assert(written == strlen(test_string) + 1);
+ assert(buf2[written - 1] == '\0');
+ assert(strcmp(buf2, test_string) == 0);
+
+ for (i = 0; i < 100; i++) {
+ len = rand() % 250;
+ memset(buf1, '\0', sizeof(buf1));
+ memset(buf2, '=', sizeof(buf2));
+ memset(buf3, '\0', sizeof(buf3));
+ for (j = 0; j < len; j++) {
+ buf1[j] = rand() & 0xFF;
+ }
+
+ j = rand() % 100;
+ BASE64_Encode(buf1, len, &read, buf2, sizeof(buf2), &written, &j);
+ assert(len == read);
+ assert (written < sizeof(buf2));
+ assert(buf2[written] == '\0');
+
+ buf2[written] = '=';
+ BASE64_Decode(buf2, written, &read, buf3, sizeof(buf3), &written);
+ assert(len == written);
+ assert(memcmp(buf1, buf3, len) == 0);
+ }
+}
+
/***********************************************************************
* TEST: Miscellaneous
@@ -291,6 +337,7 @@ int main(void)
CORE_SetLOGFILE(stderr, 0/*false*/);
TEST_URL_Encoding();
+ TEST_BASE64_Encoding();
TEST_MIME();
TEST_ConnNetInfo();
@@ -302,6 +349,18 @@ int main(void)
/*
* ---------------------------------------------------------------------------
* $Log: test_ncbi_connutil_misc.c,v $
+ * Revision 6.18 2005/04/20 18:23:26 lavr
+ * +<stdlib.h>
+ *
+ * Revision 6.17 2005/03/21 17:04:51 lavr
+ * BASE64_{En|De}code tests extended
+ *
+ * Revision 6.16 2005/03/19 02:17:08 lavr
+ * Fix change log entry
+ *
+ * Revision 6.15 2005/03/19 02:14:10 lavr
+ * +Test for BASE64_{En|De}code
+ *
* Revision 6.14 2004/04/01 14:14:02 lavr
* Spell "occurred", "occurrence", and "occurring"
*
diff --git a/connect/test/test_ncbi_core.c b/connect/test/test_ncbi_core.c
index 02160ef4..62d11888 100644
--- a/connect/test/test_ncbi_core.c
+++ b/connect/test/test_ncbi_core.c
@@ -1,4 +1,4 @@
-/* $Id: test_ncbi_core.c,v 6.9 2002/08/14 03:35:26 lavr Exp $
+/* $Id: test_ncbi_core.c,v 6.10 2005/04/20 18:23:11 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -32,6 +32,7 @@
*
*/
+#include "../ncbi_assert.h"
#include <connect/ncbi_util.h>
#include <stdlib.h>
#include <errno.h>
@@ -362,6 +363,9 @@ int main(void)
/*
* ---------------------------------------------------------------------------
* $Log: test_ncbi_core.c,v $
+ * Revision 6.10 2005/04/20 18:23:11 lavr
+ * +"../ncbi_assert.h"
+ *
* Revision 6.9 2002/08/14 03:35:26 lavr
* Fix ELOG_Level test; add eIO_Interrupt to EIO_Status test
*
diff --git a/connect/test/test_ncbi_dsock.c b/connect/test/test_ncbi_dsock.c
index 1fa884bb..d535c7b9 100644
--- a/connect/test/test_ncbi_dsock.c
+++ b/connect/test/test_ncbi_dsock.c
@@ -1,4 +1,4 @@
-/* $Id: test_ncbi_dsock.c,v 6.14 2003/12/11 15:34:29 lavr Exp $
+/* $Id: test_ncbi_dsock.c,v 6.15 2005/01/05 21:33:58 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -57,13 +57,20 @@
/* This is the maximal datagram size defined by the UDP standard */
# define MAX_DGRAM_SIZE 65535
#endif
+/* NOTE: x86_64 (AMD) kernel does not allow dgrams bigger than MTU minus
+ * small overhead; for these we use the script and pass the MTU via argv.
+ */
#define DEFAULT_PORT 55555
+static unsigned short s_MTU = MAX_DGRAM_SIZE;
+
+
static int s_Usage(const char* prog)
{
- CORE_LOGF(eLOG_Error, ("Usage:\n%s {client|server} [port [seed]]", prog));
+ CORE_LOGF(eLOG_Error, ("Usage:\n%s {client|server} [port [mtu [seed]]]",
+ prog));
return 1;
}
@@ -220,7 +227,7 @@ static int s_Client(int x_port, unsigned int max_try)
return 1;
}
- msglen = (size_t)(((double)rand()/(double)RAND_MAX)*(MAX_DGRAM_SIZE - 10));
+ msglen = (size_t)(((double)rand()/(double)RAND_MAX)*(s_MTU - 10));
if (msglen < sizeof(time_t))
msglen = sizeof(time_t);
@@ -336,17 +343,17 @@ int main(int argc, const char* argv[])
fLOG_OmitNoteLevel | fLOG_DateTime);
CORE_SetLOGFILE(stderr, 0/*false*/);
- if (argc < 2 || argc > 4)
+ if (argc < 2 || argc > 5)
return s_Usage(argv[0]);
- if (argc <= 3) {
+ if (argc <= 4) {
#ifdef NCBI_OS_UNIX
seed = (unsigned long) time(0) + (unsigned long) getpid();
#else
seed = (unsigned long) time(0);
#endif /*NCBI_OS_UNIX*/
} else
- sscanf(argv[3], "%lu", &seed);
+ sscanf(argv[4], "%lu", &seed);
CORE_LOGF(eLOG_Note, ("Random SEED = %lu", seed));
srand(seed);
@@ -358,6 +365,12 @@ int main(int argc, const char* argv[])
SOCK_SetDataLoggingAPI(eOn);
}
+ if (argc > 3) {
+ int mtu = atoi(argv[3]);
+ if (mtu > 32 && mtu < (int) s_MTU)
+ s_MTU = mtu - 32/*small protocol (IP/UDP) overhead*/;
+ }
+
if (!(env = getenv("CONN_MAX_TRY")) || !(max_try = atoi(env)))
max_try = DEF_CONN_MAX_TRY;
@@ -374,6 +387,9 @@ int main(int argc, const char* argv[])
/*
* --------------------------------------------------------------------------
* $Log: test_ncbi_dsock.c,v $
+ * Revision 6.15 2005/01/05 21:33:58 lavr
+ * Introduce MTU and use it on AMD-64 buggy kernels
+ *
* Revision 6.14 2003/12/11 15:34:29 lavr
* Lower maximal datagram size for Linux - 65535 didn't seem to work everywhere
*
diff --git a/connect/test/test_ncbi_file_connector.c b/connect/test/test_ncbi_file_connector.c
index ac464ce2..9588ec19 100644
--- a/connect/test/test_ncbi_file_connector.c
+++ b/connect/test/test_ncbi_file_connector.c
@@ -1,4 +1,4 @@
-/* $Id: test_ncbi_file_connector.c,v 6.5 2004/02/23 15:23:43 lavr Exp $
+/* $Id: test_ncbi_file_connector.c,v 6.6 2005/04/20 18:23:11 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -30,6 +30,7 @@
*
*/
+#include "../ncbi_assert.h"
#include <connect/ncbi_connection.h>
#include <connect/ncbi_file_connector.h>
#include <connect/ncbi_util.h>
@@ -120,6 +121,9 @@ int main(int argc, const char* argv[])
/*
* --------------------------------------------------------------------------
* $Log: test_ncbi_file_connector.c,v $
+ * Revision 6.6 2005/04/20 18:23:11 lavr
+ * +"../ncbi_assert.h"
+ *
* Revision 6.5 2004/02/23 15:23:43 lavr
* New (last) parameter "how" added in CONN_Write() API call
*
diff --git a/connect/test/test_ncbi_ftp_connector.c b/connect/test/test_ncbi_ftp_connector.c
new file mode 100644
index 00000000..0155115e
--- /dev/null
+++ b/connect/test/test_ncbi_ftp_connector.c
@@ -0,0 +1,159 @@
+/* $Id: test_ncbi_ftp_connector.c,v 1.3 2004/12/27 15:32:10 lavr Exp $
+ * ===========================================================================
+ *
+ * PUBLIC DOMAIN NOTICE
+ * National Center for Biotechnology Information
+ *
+ * This software/database is a "United States Government Work" under the
+ * terms of the United States Copyright Act. It was written as part of
+ * the author's official duties as a United States Government employee and
+ * thus cannot be copyrighted. This software/database is freely available
+ * to the public for use. The National Library of Medicine and the U.S.
+ * Government have not placed any restriction on its use or reproduction.
+ *
+ * Although all reasonable efforts have been taken to ensure the accuracy
+ * and reliability of the software and data, the NLM and the U.S.
+ * Government do not and cannot warrant the performance or results that
+ * may be obtained by using this software or data. The NLM and the U.S.
+ * Government disclaim all warranties, express or implied, including
+ * warranties of performance, merchantability or fitness for any particular
+ * purpose.
+ *
+ * Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author: Anton Lavrentiev
+ *
+ * File Description:
+ * Test case for FTP-based CONNECTOR
+ *
+ */
+
+#include "../ncbi_ansi_ext.h"
+#include "../ncbi_priv.h"
+#include <connect/ncbi_connection.h>
+#include <connect/ncbi_ftp_connector.h>
+#include <stdlib.h>
+/* This header must go last */
+#include "test_assert.h"
+
+
+#define TEST_HOST "ftp.ncbi.nlm.nih.gov"
+#define TEST_PORT 0
+#define TEST_USER "ftp"
+#define TEST_PASS "none"
+#define TEST_PATH "/"
+
+
+int main(int argc, char* argv[])
+{
+ static const char chdir[] = "CWD /toolbox/ncbi_tools\n";
+ static const char file[] = "RETR CURRENT/ncbi.tar.gz";
+ const char* env = getenv("CONN_DEBUG_PRINTOUT");
+ int/*bool*/ aborting = 0;
+ STimeout timeout;
+ CONNECTOR connector;
+ FILE* data_file;
+ CONN conn;
+ ESwitch log = eDefault;
+ size_t n;
+ char buf[1024];
+ EIO_Status status;
+
+ /* Log and data-log streams */
+ CORE_SetLOGFormatFlags(fLOG_None | fLOG_Level |
+ fLOG_OmitNoteLevel | fLOG_DateTime);
+ CORE_SetLOGFILE(stderr, 0/*false*/);
+ data_file = fopen("test_ncbi_ftp_connector.log", "wb");
+ assert(data_file);
+
+ timeout.sec = 3;
+ timeout.usec = 0;
+
+ if (env && (strcasecmp(env, "1") == 0 ||
+ strcasecmp(env, "TRUE") == 0 ||
+ strcasecmp(env, "SOME") == 0 ||
+ strcasecmp(env, "DATA") == 0)) {
+ log = eOn;
+ }
+ if (env && (strcasecmp(env, "0") == 0 ||
+ strcasecmp(env, "NONE") == 0 ||
+ strcasecmp(env, "FALSE") == 0)) {
+ log = eOff;
+ }
+
+ /* Run the tests */
+ connector = FTP_CreateDownloadConnector(TEST_HOST, TEST_PORT,
+ TEST_USER, TEST_PASS,
+ TEST_PATH, log);
+
+ if (CONN_Create(connector, &conn) != eIO_Success)
+ CORE_LOG(eLOG_Fatal, "Cannot create FTP download connection");
+
+ if (CONN_Read(conn, buf, sizeof(buf), &n, eIO_ReadPlain) != eIO_Closed)
+ CORE_LOG(eLOG_Fatal, "Test failed in empty READ");
+
+ if (CONN_Write(conn, "aaa", 3, &n, eIO_WritePlain) != eIO_Success)
+ CORE_LOG(eLOG_Fatal, "Cannot write FTP command");
+
+ if (CONN_Wait(conn, eIO_Read, &timeout) != eIO_Unknown)
+ CORE_LOG(eLOG_Fatal, "Test failed in waiting on READ");
+
+ if (CONN_Write(conn, "LIST", 4, &n, eIO_WritePlain) != eIO_Success)
+ CORE_LOG(eLOG_Fatal, "Cannot write LIST command");
+
+ do {
+ status = CONN_Read(conn, buf, sizeof(buf), &n, eIO_ReadPlain);
+ if (n != 0)
+ printf("%.*s", (int) n, buf);
+ } while (status == eIO_Success);
+
+ if (CONN_Write(conn, chdir, sizeof(chdir) - 1, &n, eIO_WritePlain)
+ != eIO_Success) {
+ CORE_LOGF(eLOG_Fatal, ("Cannot execute %.*s",
+ (int)sizeof(chdir) - 2, chdir));
+ }
+
+ if (CONN_Write(conn, file, sizeof(file) - 1, &n, eIO_WritePersist)
+ != eIO_Success) {
+ CORE_LOGF(eLOG_Fatal, ("Cannot write %s", file));
+ }
+
+ do {
+ status = CONN_Read(conn, buf, sizeof(buf), &n, eIO_ReadPlain);
+ if (n != 0)
+ fwrite(buf, n, 1, data_file);
+ if (argc > 1 && rand() % 100 == 0) {
+ aborting = 1;
+ break;
+ }
+ } while (status == eIO_Success);
+
+ if (CONN_Close(conn) != eIO_Success)
+ CORE_LOGF(eLOG_Fatal, ("Error %s FTP connection",
+ aborting ? "aborting" : "closing"));
+
+ /* Cleanup and Exit */
+ fclose(data_file);
+ if (aborting)
+ remove("test_ncbi_ftp_connector.log");
+ CORE_SetLOG(0);
+ return 0;
+}
+
+
+/*
+ * --------------------------------------------------------------------------
+ * $Log: test_ncbi_ftp_connector.c,v $
+ * Revision 1.3 2004/12/27 15:32:10 lavr
+ * Randomly test ABORTs (if there is an argument for main())
+ *
+ * Revision 1.2 2004/12/06 22:02:51 ucko
+ * +<stdlib.h> for getenv()
+ *
+ * Revision 1.1 2004/12/06 17:49:00 lavr
+ * Initial revision
+ *
+ * ==========================================================================
+ */
diff --git a/connect/test/test_ncbi_http_connector.c b/connect/test/test_ncbi_http_connector.c
index ab4adefb..7c8f9f5c 100644
--- a/connect/test/test_ncbi_http_connector.c
+++ b/connect/test/test_ncbi_http_connector.c
@@ -1,4 +1,4 @@
-/* $Id: test_ncbi_http_connector.c,v 6.15 2004/04/01 14:14:02 lavr Exp $
+/* $Id: test_ncbi_http_connector.c,v 6.18 2004/11/23 15:04:39 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -41,9 +41,9 @@
/* Hard-coded pseudo-registry getter
*/
-#define TEST_HOST "yar.ncbi.nlm.nih.gov"
-#define TEST_PORT "6224"
-#define TEST_PATH "/tools/vakatov/con_url.cgi"
+#define TEST_HOST "www.ncbi.nlm.nih.gov"
+#define TEST_PORT "80"
+#define TEST_PATH "/Service/bounce.cgi"
#define TEST_ARGS "arg1+arg2+arg3"
#define TEST_DEBUG_PRINTOUT "yes"
#define TEST_REQ_METHOD "any"
@@ -142,6 +142,15 @@ int main(void)
/*
* --------------------------------------------------------------------------
* $Log: test_ncbi_http_connector.c,v $
+ * Revision 6.18 2004/11/23 15:04:39 lavr
+ * Use public bounce.cgi from "www"
+ *
+ * Revision 6.17 2004/11/22 20:27:32 lavr
+ * Weird 5.123456 timeout restored to the form it used to be
+ *
+ * Revision 6.16 2004/11/22 20:25:27 lavr
+ * "yar" replaced with "graceland"
+ *
* Revision 6.15 2004/04/01 14:14:02 lavr
* Spell "occurred", "occurrence", and "occurring"
*
diff --git a/connect/test/test_ncbi_http_get.c b/connect/test/test_ncbi_http_get.c
index bd1dfff2..7876f201 100644
--- a/connect/test/test_ncbi_http_get.c
+++ b/connect/test/test_ncbi_http_get.c
@@ -1,4 +1,4 @@
-/* $Id: test_ncbi_http_get.c,v 6.12 2003/09/30 20:59:39 lavr Exp $
+/* $Id: test_ncbi_http_get.c,v 6.14 2005/04/20 15:51:19 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -34,6 +34,7 @@
#include "../ncbi_priv.h"
#include <connect/ncbi_http_connector.h>
#include <connect/ncbi_util.h>
+#include <errno.h>
#include <stdlib.h>
#include <time.h>
#ifdef NCBI_OS_UNIX
@@ -48,8 +49,11 @@ int main(int argc, char* argv[])
static const STimeout s_ZeroTmo = {0, 0};
CONNECTOR connector;
SConnNetInfo* net_info;
+ char blk[512];
+ EIO_Status status;
THCC_Flags flags;
CONN conn;
+ FILE* fp;
time_t t;
size_t n;
char* s;
@@ -58,15 +62,22 @@ int main(int argc, char* argv[])
fLOG_OmitNoteLevel | fLOG_DateTime);
CORE_SetLOGFILE(stderr, 0/*false*/);
- if (argc != 2 || !*argv[1]) {
- CORE_LOG(eLOG_Error, "URL has to be supplied on the command line");
- exit(1);
- }
+ if (argc < 2 || !*argv[1])
+ CORE_LOG(eLOG_Fatal, "URL has to be supplied on the command line");
+ if (argc > 3)
+ CORE_LOG(eLOG_Fatal, "Command cannot take more than 2 arguments");
+ if (argc == 3) {
+ fp = strcmp(argv[2], "-") == 0 ? stdin : fopen(argv[2], "rb");
+ if (!fp) {
+ CORE_LOGF_ERRNO(eLOG_Error, errno, ("Cannot open \"%s\"",
+ argv[2] ? argv[2] : ""));
+ }
+ } else
+ fp = 0;
CORE_LOG(eLOG_Note, "Creating network info structure");
if (!(net_info = ConnNetInfo_Create(0)))
CORE_LOG(eLOG_Fatal, "Cannot create network info structure");
- net_info->req_method = eReqMethod_Get;
if ((s = getenv("CONN_TIMEOUT")) && strcmp(s, "0") == 0) {
memcpy(&net_info->tmo, &s_ZeroTmo, sizeof(s_ZeroTmo));
net_info->timeout = &net_info->tmo;
@@ -93,12 +104,19 @@ int main(int argc, char* argv[])
CORE_LOG(eLOG_Fatal, "Cannot create connection");
CONN_SetTimeout(conn, eIO_Open, net_info->timeout);
CONN_SetTimeout(conn, eIO_ReadWrite, net_info->timeout);
+ while (fp && !feof(fp)) {
+ n = fread(blk, 1, sizeof(blk), fp);
+ status = CONN_Write(conn, blk, n, &n, eIO_WritePersist);
+ if (status != eIO_Success) {
+ CORE_LOGF(eLOG_Fatal, ("Write error: %s", IO_StatusStr(status)));
+ }
+ }
+ if (fp)
+ fclose(fp);
t = time(0);
for (;;) {
- char blk[512];
- EIO_Status status = CONN_Wait(conn, eIO_Read, net_info->timeout);
-
+ status = CONN_Wait(conn, eIO_Read, net_info->timeout);
if (status != eIO_Success) {
if (status == eIO_Closed)
break;
@@ -135,6 +153,12 @@ int main(int argc, char* argv[])
/*
* --------------------------------------------------------------------------
* $Log: test_ncbi_http_get.c,v $
+ * Revision 6.14 2005/04/20 15:51:19 lavr
+ * Allow addtl file argument to attach as a body ('-' for stdin)
+ *
+ * Revision 6.13 2005/04/19 16:37:52 lavr
+ * Allow HTTP method to be overridden from the environment
+ *
* Revision 6.12 2003/09/30 20:59:39 lavr
* Fix typo in previous log message
*
diff --git a/connect/test/test_ncbi_mac_mit_socket.c b/connect/test/test_ncbi_mac_mit_socket.c
deleted file mode 100755
index 9fb65309..00000000
--- a/connect/test/test_ncbi_mac_mit_socket.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/* testmain.c
- *
- * Simple test routines for the DNR and socket interfaces that are
- * linked from Sequin. A friendlier user interface would be nice...
- *
- * 02/27/00 pjc
- * Added utility printing function and tests for 6 more functions
- *
- * 02/26/00 pjc
- * gethostbyname and gethostbyaddr: first working
- *
- * Created 1/15/00 by pchurchill
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <s_socket.h>
-#include <OpenTptInternet.h> // for TCP/IP
-#include <netdb.h>
-#include <neti_in.h>
-#include <a_inet.h>
-
-/* printIP
- *
- * Utility function for printing out IP addresses during
- * debugging
- */
-int printIP( char** theAddr)
-{
- int i = 0;
- unsigned char *b;
- unsigned long **x = (unsigned long **) theAddr;
-
- while( (theAddr[i] != 0) && (i < kMaxHostAddrs)){
- b = (unsigned char *) theAddr[i];
- printf( "IP address for 0x%lx \t", *x[i]);
- printf( "is %d.%d.%d.%d\n",b[0],b[1],b[2],b[3]);
- i++;
- }
- printf("\n");
- return 0;
-}
-
-/* printHNames
- *
- * Utility function to print out the fully qualified hostname
- * along with any aliases that were identified
- */
-void printHNames( struct hostent* info)
-{
- int i = 0;
-
- printf("Fully qualified hostname: %s\n", info->h_name);
- printf("Also reported the aliases: ");
- while( info->h_aliases[i] != NULL){
- printf("%s, ", info->h_aliases[i]);
- i++;
- }
- printf("\n");
- return;
-}
-
-
-void testGetHostByName( const char* hostname)
-{
- struct hostent *ans = NULL;
-
- printf("Calling gethostbyname() for '%s'\n", hostname);
- ans = gethostbyname(hostname);
- if( ans != NULL){
- printIP( &ans->h_addr_list[0]);
- printHNames( ans);
- }
- else{
- printf("gethostbyname returned 'NULL'.\n\terrno reads as %d\n",ncbi_GetErrno());
- }
- printf("\n");
- return;
-}
-
-void testGetHostByAddr( InetHost theAddr)
-{
- struct hostent *ans = NULL;
-
- printf("Calling gethostbyaddr() for '%8lx'\n", theAddr);
- ans = gethostbyaddr( &theAddr, 4, AF_INET);
- if( ans != NULL){
- printIP( &ans->h_addr_list[0]);
- printHNames( ans);
- }
- else{
- printf("Hmm, gethostbyaddr returned 'NULL'. Need to implement errno\n");
- }
- printf("\n");
- return;
-}
-
-void testGetHostID( void)
-{
- unsigned char *b;
- InetHost hostid;
-
- printf("About to call gethostid()\n");
- hostid = gethostid();
- if( hostid == 0){
- printf("gethostid returned 0. Need to implement errno\n");
- }
- else{
- b = (unsigned char *) &hostid;
- printf("gethostid() returned 0x%8x, %d.%d.%d.%d\n\n", hostid,
- b[0],b[1],b[2],b[3]);
- }
- return;
-}
-
-void testGetHostName( void)
-{
- char myname[255];
- int ans = 0;
-
- printf("About to call gethostname()\n");
- ans = gethostname( myname, 255);
- if( ans != 0){
- printf("gethostname returned 0. Need to implement errno\n");
- }
- else{
- printf("gethostname() returned %s\n\n", myname);
- }
- return;
-}
-
-/* testInet_ntoa
- *
- * test the address utility that converts IP addresses from network
- * to host byte ordering (this is trivial on a Mac, they are both
- * in the same order)
- */
-void testInet_ntoa( InetHost x)
-{
- char* ans;
- struct in_addr addr;
-
- addr.s_addr = x;
- printf("About to call inet_ntoa for 0x%8x\n", x);
- ans = inet_ntoa( addr);
- if( ans != NULL){
- printf("inet_ntoa returned: %s\n\n", ans);
- }
- else{
- printf("inet_ntoa returned NULL, Need to implement errno\n");
- }
- return;
-}
-
-/* testInet_aton
- *
- * tests utility that converts from dotted decimal notation (string)
- * to internet host address (hex). Both input and output are through
- * parameters passed to the function.
- */
-void testInet_aton( const char* string)
-{
- int error;
- struct in_addr addr;
-
- printf("About to call inet_aton for %s\n", string);
- error = inet_aton( string, &addr);
- if( error == INET_SUCCESS){
- printf("inet_aton returned: 0x%8x\n\n", addr.s_addr);
- }
- else{
- printf("inet_ntoa returned %d\n\n", error);
- }
- return;
-}
-
-
-/* testInet_addr
- *
- * tests utility that converts from dotted decimal notation (string)
- * to internet host address (hex)
- */
-void testInet_addr( const char* string)
-{
- InetHost addr;
-
- printf("About to call inet_addr for %s\n", string);
- addr = inet_addr( string);
- printf("inet_addr returned: 0x%8x\n\n", addr);
- return;
-}
-
-/* testGetServByName
- *
- */
-void testGetServByName( void)
-{
- struct servent *ans;
- char *proto[] = {"udp","tcp"};
- char *serv[] = {"ftp","http","gopher","nfs","\0"};
- int i;
-
- for( i = 0; serv[i] != "\0"; i++){
- printf("\nCalling getservbyname for %s, %s\n", serv[i], proto[1]);
- ans = getservbyname( serv[i], proto[1]);
- if( ans != NULL){
- printf(" getservbyname: returned %s, %s, %d\n",
- ans->s_name, ans->s_proto, ans->s_port);
- } else{
- printf(" getservbyname: Returned NULL, maybe it doesn't exist?\n");
- }
- }
- return;
-}
-
-
-/* testGetServByPort
- *
- */
-void testGetServByPort( void)
-{
- struct servent *udpAns, *tcpAns;
- char ans1[32], ans2[32];
- int i;
-
- printf("Testing getservbyport, by scanning the first 255 ports\n\n");
- printf("Port #: udp service tcp service\n");
- for( i=0; i<=255; i++){
- udpAns = getservbyport( i, "udp");
- if( udpAns){
- strncpy( ans1, udpAns->s_name, 30);
- }
- tcpAns = getservbyport( i, "tcp");
- if( tcpAns){
- strncpy( ans2, tcpAns->s_name, 30);
- }
- if( (udpAns == NULL) && (tcpAns == NULL)){
- continue;
- }
- printf(" %3d: ", i);
- if( udpAns){
- printf("%12s", ans1);
- }
- if( tcpAns){
- printf("%14s", ans2);
- }
- printf("\n");
- }
- return;
-}
-
-
-/* main
- *
- */
-
-int main( void)
-{
- // for now, just call the functions. don't do anything real ;-)
-
- printf("Hello, this is Phil's OT dnr tester\n\n");
-
- // first, test functions that don't require network
- testInet_ntoa( 0x80082680);
- testInet_aton( "128.8.38.128");
- testInet_addr( "38.128.8.128");
- testGetServByName();
- // This test takes quite a while to run...
- // testGetServByPort();
-
- // next get info about our local machine
- testGetHostID();
- testGetHostName();
-
- // then lookup a few others to see if they work...
- testGetHostByAddr( 0x80082680);
- testGetHostByName( "www.apple.com");
- testGetHostByName( "www.churchillandassociates.com");
- testGetHostByName( "mail");
- // one that should fail...
- testGetHostByName( "foo.dev.com");
-
-// s_socket(); // create the socket
-// s_close(); // close it (free the resources)
-// s_connect(); // connect using udp or tcp
-// s_send(); // just send # bytes
-// s_write(); // similar, but datagram oriented
-// s_recv(); // just get the next n bytes
-// s_read(); // similar, but datagram oriented
-// s_setsockopt();
-// s_accept();
-// s_listen();
-// s_bind();
-// s_fcntl();
-/*
- bzero(); // unchanged from ncsalib
- */
- return 0;
-}
-
diff --git a/connect/test/test_ncbi_sendmail.c b/connect/test/test_ncbi_sendmail.c
index 47f884f6..c3ea3d8a 100644
--- a/connect/test/test_ncbi_sendmail.c
+++ b/connect/test/test_ncbi_sendmail.c
@@ -1,4 +1,4 @@
-/* $Id: test_ncbi_sendmail.c,v 6.11 2003/12/09 15:39:30 lavr Exp $
+/* $Id: test_ncbi_sendmail.c,v 6.13 2005/03/21 17:30:28 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -31,7 +31,9 @@
*/
#include "../ncbi_priv.h" /* CORE logging facilities */
+#include "../ncbi_ansi_ext.h"
#include <connect/ncbi_sendmail.h>
+#include <connect/ncbi_socket.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -58,6 +60,7 @@ int main(void)
".\n",
"",
"a\nb\nc\nd\n.",
+ "a\r\n\rb\r\nc\r\nd\r\n.",
".\na"
};
const char* subject[] = {
@@ -70,19 +73,27 @@ int main(void)
"lavr@pavo",
" \"Anton Lavrentiev\" <lavr@pavo> , lavr, <lavr> ",
};
+ const char* mx_host, *p;
size_t i, j, k, n, m;
- const char* mx_host;
SSendMailInfo info;
const char* retval;
STimeout mx_tmo;
char* huge_body;
short mx_port;
- FILE *fp;
+ FILE* fp;
CORE_SetLOGFormatFlags(fLOG_None | fLOG_Level |
fLOG_OmitNoteLevel | fLOG_DateTime);
CORE_SetLOGFILE(stderr, 0/*false*/);
srand(time(0));
+ if ((p = getenv("CONN_DEBUG_PRINTOUT")) != 0) {
+ if (strncasecmp(p, "1", 1) == 0 ||
+ strncasecmp(p, "YES", 3) == 0 ||
+ strncasecmp(p, "SOME", 4) == 0 ||
+ strncasecmp(p, "DATA", 4) == 0) {
+ SOCK_SetDataLoggingAPI(eOn);
+ }
+ }
CORE_LOG(eLOG_Note, "Phase 1 of 2: Testing CORE_SendMail");
@@ -246,6 +257,12 @@ int main(void)
/*
* --------------------------------------------------------------------------
* $Log: test_ncbi_sendmail.c,v $
+ * Revision 6.13 2005/03/21 17:30:28 lavr
+ * Include "../ncbi_ansi_ext.h" (essential for Windows)
+ *
+ * Revision 6.12 2005/03/18 16:36:10 lavr
+ * Additional test for \r\n in body; debug output provision
+ *
* Revision 6.11 2003/12/09 15:39:30 lavr
* Added new test of custom-sized message body
*
diff --git a/connect/test/test_ncbi_service_connector.c b/connect/test/test_ncbi_service_connector.c
index 5b474241..81d70005 100644
--- a/connect/test/test_ncbi_service_connector.c
+++ b/connect/test/test_ncbi_service_connector.c
@@ -1,4 +1,4 @@
-/* $Id: test_ncbi_service_connector.c,v 6.29 2004/02/23 15:23:43 lavr Exp $
+/* $Id: test_ncbi_service_connector.c,v 6.31 2005/01/28 17:44:48 lavr Exp $
* ===========================================================================
*
* PUBLIC DOMAIN NOTICE
@@ -43,9 +43,10 @@ int main(int argc, const char* argv[])
static char obuf[8192 + 2] = "UUUUUZZZZZZUUUUUUZUZUZZUZUZUZUZUZ\n";
const char* service = argc > 1 && *argv[1] ? argv[1] : "bounce";
const char* host = argc > 2 && *argv[2] ? argv[2] : "www.ncbi.nlm.nih.gov";
- SConnNetInfo *net_info;
+ SConnNetInfo* net_info;
CONNECTOR connector;
EIO_Status status;
+ STimeout* timeout;
char ibuf[1024];
CONN conn;
size_t n;
@@ -61,9 +62,9 @@ int main(int argc, const char* argv[])
obuf[++n] = 0;
}
strcpy(net_info->args, "testarg=testval&service=none");
+ timeout = net_info->timeout;
connector = SERVICE_CreateConnectorEx(service, fSERV_Any, net_info, 0);
- ConnNetInfo_Destroy(net_info);
if (!connector)
CORE_LOG(eLOG_Fatal, "Failed to create service connector");
@@ -99,10 +100,7 @@ int main(int argc, const char* argv[])
#endif
for (;;) {
- STimeout timeout;
- timeout.sec = 5;
- timeout.usec = 12345;
- if (CONN_Wait(conn, eIO_Read, &timeout) != eIO_Success) {
+ if (CONN_Wait(conn, eIO_Read, timeout) != eIO_Success) {
CONN_Close(conn);
CORE_LOG(eLOG_Fatal, "Error waiting for reading");
}
@@ -150,6 +148,8 @@ int main(int argc, const char* argv[])
CORE_LOG(eLOG_Fatal, "Error reading from service ID1");
}
+
+ ConnNetInfo_Destroy(net_info);
CORE_LOGF(eLOG_Note, ("%d bytes read from service ID1", n));
CONN_Close(conn);
#endif
@@ -162,6 +162,12 @@ int main(int argc, const char* argv[])
/*
* --------------------------------------------------------------------------
* $Log: test_ncbi_service_connector.c,v $
+ * Revision 6.31 2005/01/28 17:44:48 lavr
+ * Fix: forgotten to merge status variable relocation
+ *
+ * Revision 6.30 2005/01/28 17:41:22 lavr
+ * Allow CONN_TIMEOUT from the environment to be used in Wait-on-Read
+ *
* Revision 6.29 2004/02/23 15:23:43 lavr
* New (last) parameter "how" added in CONN_Write() API call
*
diff --git a/connect/test/test_ncbisock.c b/connect/test/test_ncbisock.c
deleted file mode 100644
index ca20b1ba..00000000
--- a/connect/test/test_ncbisock.c
+++ /dev/null
@@ -1,647 +0,0 @@
-/* $Id: test_ncbisock.c,v 6.1 1999/10/18 15:40:50 vakatov Exp $
- * ===========================================================================
- *
- * PUBLIC DOMAIN NOTICE
- * National Center for Biotechnology Information
- *
- * This software/database is a "United States Government Work" under the
- * terms of the United States Copyright Act. It was written as part of
- * the author's official duties as a United States Government employee and
- * thus cannot be copyrighted. This software/database is freely available
- * to the public for use. The National Library of Medicine and the U.S.
- * Government have not placed any restriction on its use or reproduction.
- *
- * Although all reasonable efforts have been taken to ensure the accuracy
- * and reliability of the software and data, the NLM and the U.S.
- * Government do not and cannot warrant the performance or results that
- * may be obtained by using this software or data. The NLM and the U.S.
- * Government disclaim all warranties, express or implied, including
- * warranties of performance, merchantability or fitness for any particular
- * purpose.
- *
- * Please cite the author in any work or product based on this material.
- *
- * ===========================================================================
- *
- * Author: Denis Vakatov
- *
- * File Description:
- * Test suite for "ncbisock.[ch]"
- *
- * ---------------------------------------------------------------------------
- * $Log: test_ncbisock.c,v $
- * Revision 6.1 1999/10/18 15:40:50 vakatov
- * Initial revision
- *
- * ===========================================================================
- */
-
-#include <ncbilcl.h>
-#if defined(OS_UNIX)
-# include <unistd.h>
-# define X_SLEEP(x) ((void) sleep(x))
-#elif defined(OS_MSWIN)
-# include <windows.h>
-# define X_SLEEP(x) ((void) Sleep(1000 * x))
-#else
-# define X_SLEEP(x) ((void) 0)
-#endif
-
-#include <ncbi.h>
-#include <ncbisock.h>
-
-
-#define TEST_BUFSIZE 8192
-
-/* exit server before sending the data expected by client(Test 1) */
-/*#define TEST_SRV1_SHUTDOWN*/
-
-#ifndef TEST_SRV1_SHUTDOWN
-/* exit server immediately after its first client is served(Test 1) */
-/*#define TEST_SRV1_ONCE*/
-#endif
-
-
-#define ASS_RET(expr,retcode) \
-if ( !(expr) ) { ASSERT ( 0 ); return retcode; } else {;}
-
-
-/* The simplest randezvous(plain request-reply) test functions
- * "TEST__client_1(SOCK sock)"
- * "TEST__server_1(SOCK sock)"
- */
-
-static const char s_C1[] = "C1";
-static const char s_S1[] = "S1";
-
-#define N_SUB_BLOB 10
-#define SUB_BLOB_SIZE 7000
-#define BIG_BLOB_SIZE (N_SUB_BLOB * SUB_BLOB_SIZE)
-
-
-static Int2 TEST__client_1(SOCK sock)
-{ /* reserved ret.codes [110-119] */
- ESOCK_ErrCode err_code;
- Uint4 n_io, n_io_done;
- char buf[TEST_BUFSIZE];
-
- ErrPostEx(SEV_INFO, SOCK_ERRCODE, 110, "TC1()");
-
- /* Send a short string */
- n_io = StrLen(s_C1) + 1;
- err_code = SOCK_Write(sock, s_C1, n_io, &n_io_done);
- ASS_RET((err_code == eSOCK_ESuccess && n_io == n_io_done), 101);
-
- n_io = StrLen(s_S1) + 1;
- err_code = SOCK_Read(sock, buf, n_io, &n_io_done);
- if (err_code == eSOCK_EClosed) {
- ErrPostEx(SEV_WARNING, SOCK_ERRCODE, 103, "TC1(): connection closed");
- return 103;
- }
- ASS_RET((err_code == eSOCK_ESuccess && n_io == n_io_done), 104);
- ASS_RET((StrCmp(buf, s_S1) == 0), 105);
- ASS_RET(SOCK_PushBack(sock, buf, n_io_done) == eSOCK_ESuccess, 106);
- MemSet(buf, '\xFF', n_io_done);
- ASS_RET(SOCK_Read(sock, buf, n_io_done, &n_io_done) == eSOCK_ESuccess, 107);
- ASS_RET((StrCmp(buf, s_S1) == 0), 108);
-
- /* Send a very big binary blob */
- {{
- size_t i;
- char* blob = (char*) MemNew(BIG_BLOB_SIZE);
- for (i = 0; i < BIG_BLOB_SIZE; blob[i] = (char)i, i++)
- continue;
- for (i = 0; i < 10; i++) {
- err_code = SOCK_Write(sock, blob + i * SUB_BLOB_SIZE, SUB_BLOB_SIZE,
- &n_io_done);
- ASS_RET((err_code == eSOCK_ESuccess && n_io_done==SUB_BLOB_SIZE), 109);
- }
- MemFree(blob);
- }}
-
- return 0;
-}
-
-
-static Int2 TEST__server_1(SOCK sock)
-{ /* reserved ret.codes [210-219] */
- ESOCK_ErrCode err_code;
- Uint4 n_io, n_io_done;
- char buf[TEST_BUFSIZE];
-
- ErrPostEx(SEV_INFO, SOCK_ERRCODE, 210, "TS1()");
-
- /* Receive and send back a short string */
- n_io = StrLen(s_C1) + 1;
- err_code = SOCK_Read(sock, buf, n_io, &n_io_done);
- ASS_RET((err_code == eSOCK_ESuccess && n_io == n_io_done), 210);
- ASS_RET((StrCmp(buf, s_C1) == 0), 211);
-
-#ifdef TEST_SRV1_SHUTDOWN
- return 212;
-#endif
-
- n_io = StrLen(s_S1) + 1;
- err_code = SOCK_Write(sock, s_S1, n_io, &n_io_done);
- ASS_RET((err_code == eSOCK_ESuccess && n_io == n_io_done), 213);
-
- /* Receive a very big binary blob, and check its content */
- {{
- char* blob = (char*)MemNew(BIG_BLOB_SIZE);
- err_code = SOCK_ReadPersist(sock, blob, BIG_BLOB_SIZE, &n_io_done);
- ASS_RET((err_code == eSOCK_ESuccess && n_io_done == BIG_BLOB_SIZE), 214);
- for (n_io = 0; n_io < BIG_BLOB_SIZE; n_io++)
- ASSERT( blob[n_io] == (char)n_io );
- MemFree(blob);
- }}
-
- return 0;
-}
-
-
-/* More complicated randezvous test functions
- * "TEST__client_2(SOCK sock)"
- * "TEST__server_2(SOCK sock)"
- */
-
-static void s_DoubleTimeout(STimeout *to) {
- if (!to->sec && !to->usec) {
- to->usec = 1;
- } else {
- to->sec = 2 * to->sec + (2 * to->usec) / 1000000;
- to->usec = (2 * to->usec) % 1000000;
- }
-}
-
-static Int2 TEST__client_2(SOCK sock)
-{ /* reserved ret.codes [120-139] */
-#define W_FIELD 10
-#define N_FIELD 1000
-#define N_REPEAT 10
-#define N_RECONNECT 3
- ESOCK_ErrCode err_code;
- Uint4 n_io, n_io_done, i;
- char buf[W_FIELD * N_FIELD + 1];
-
- ErrPostEx(SEV_INFO, SOCK_ERRCODE, 110, "TC2()");
-
- /* fill out a buffer to send to server */
- MemSet(buf, '\0', sizeof(buf));
- for (i = 0; i < N_FIELD; i++) {
- sprintf(buf + i * W_FIELD, "%10lu", (unsigned long)i);
- }
-
- /* send the buffer to server, then get it back */
- for (i = 0; i < N_REPEAT; i++)
- {
- char buf1[sizeof(buf)];
- STimeout w_to, r_to;
- Boolean w_timeout_on = (Boolean) (i%2 != 0); /* if to start from */
- Boolean r_timeout_on = (Boolean) (i%3 != 0); /* zero or inf. timeout */
- char* x_buf;
-
- /* set timeout */
- w_to.sec = 0;
- w_to.usec = 0;
- err_code = SOCK_SetTimeout(sock, eSOCK_OnWrite,
- (w_timeout_on ? &w_to : 0), 0, 0);
- ASS_RET((err_code == eSOCK_ESuccess), 111);
-
-#ifdef DO_RECONNECT
- /* reconnect */
- if ((i % N_RECONNECT) == 0) {
- Uint4 j = i / N_RECONNECT;
- do {
- err_code = SOCK_Reconnect(sock, 0, 0, 0);
- ErrPostEx(SEV_INFO, SOCK_ERRCODE, 117,
- "TC2:reconnect: i=%d, err_code=%d",
- (int)i, (int)err_code);
- ASS_RET((err_code == eSOCK_ESuccess), 117);
- ASSERT( !SOCK_Eof(sock) );
-
- /* give a break to let server to reset the listening socket */
- X_SLEEP(1);
- } while ( j-- );
- }
-#endif
-
- /* send */
- x_buf = buf;
- n_io = sizeof(buf);
- do {
- X_SLEEP(1);
- err_code = SOCK_Write(sock, x_buf, n_io, &n_io_done);
- if (err_code == eSOCK_EClosed) {
- ErrPostEx(SEV_ERROR, SOCK_ERRCODE, 112,
- "TC2:write: connection closed");
- return 112;
- }
- ErrPostEx(SEV_INFO, SOCK_ERRCODE, 113,
- "TC2:write: i=%d, err_code=%d, n_io=%5lu, n_io_done=%5lu"
- "\ntimeout(%d): %5lu sec, %6lu msec",
- (int)i, (int)err_code,
- (unsigned long)n_io, (unsigned long)n_io_done,
- (int)w_timeout_on,
- (unsigned long)w_to.sec, (unsigned long)w_to.usec);
- if ( !w_timeout_on ) {
- ASS_RET((err_code == eSOCK_ESuccess && n_io_done == n_io), 113);
- } else {
- STimeout x_to;
- ASS_RET((err_code == eSOCK_ESuccess || err_code == eSOCK_ETimeout),
- 114);
- ASS_RET((SOCK_SetTimeout(sock, eSOCK_OnWrite, SOCK_GET_TIMEOUT,
- 0, &x_to) == eSOCK_ESuccess &&
- w_to.sec == x_to.sec && w_to.usec == x_to.usec), 115);
- }
- n_io -= n_io_done;
- x_buf += n_io_done;
- if (err_code == eSOCK_ETimeout)
- s_DoubleTimeout(&w_to);
- err_code = SOCK_SetTimeout(sock, eSOCK_OnWrite, &w_to, 0, 0);
- ASS_RET((err_code == eSOCK_ESuccess), 116);
- w_timeout_on = TRUE;
- } while ( n_io );
-
- /* get back the just sent data */
- r_to.sec = 0;
- r_to.usec = 0;
- err_code = SOCK_SetTimeout(sock, eSOCK_OnRead,
- (r_timeout_on ? &r_to : 0), 0, 0);
- ASS_RET((err_code == eSOCK_ESuccess), 121);
-
- x_buf = buf1;
- n_io = sizeof(buf1);
- do {
- if (i%2 == 0)
- { /* peek a little piece twice and compare */
- char xx_buf1[128], xx_buf2[128];
- Uint4 xx_io_done1, xx_io_done2;
- if (SOCK_Peek(sock, xx_buf1, sizeof(xx_buf1), &xx_io_done1)
- == eSOCK_ESuccess &&
- SOCK_Peek(sock, xx_buf2, xx_io_done1, &xx_io_done2)
- == eSOCK_ESuccess) {
- ASSERT ( xx_io_done1 >= xx_io_done2 );
- VERIFY ( !MemCmp(xx_buf1, xx_buf2, xx_io_done2) );
- }
- }
- err_code = SOCK_Read(sock, x_buf, n_io, &n_io_done);
- if (err_code == eSOCK_EClosed) {
- ErrPostEx(SEV_ERROR, SOCK_ERRCODE, 122,
- "TC2:read: connection closed");
- ASSERT( SOCK_Eof(sock) );
- return 122;
- }
- ErrPostEx(SEV_INFO, SOCK_ERRCODE, 123,
- "TC2:read: i=%d, err_code=%d, n_io=%5lu, n_io_done=%5lu"
- "\ntimeout(%d): %5lu sec, %6lu msec",
- (int)i, (int)err_code,
- (unsigned long)n_io, (unsigned long)n_io_done,
- (int)r_timeout_on,
- (unsigned long)r_to.sec, (unsigned long)r_to.usec);
- if ( !r_timeout_on ) {
- ASS_RET((err_code == eSOCK_ESuccess && n_io_done > 0), 124);
- } else {
- STimeout x_to;
- ASS_RET((err_code == eSOCK_ESuccess || err_code == eSOCK_ETimeout),
- 125);
- ASS_RET((SOCK_SetTimeout(sock, eSOCK_OnRead, SOCK_GET_TIMEOUT,
- &x_to, 0) == eSOCK_ESuccess &&
- r_to.sec == x_to.sec && r_to.usec == x_to.usec), 126);
- }
-
- n_io -= n_io_done;
- x_buf += n_io_done;
- if (err_code == eSOCK_ETimeout)
- s_DoubleTimeout(&r_to);
- err_code = SOCK_SetTimeout(sock, eSOCK_OnRead, &r_to, 0, 0);
- ASS_RET((err_code == eSOCK_ESuccess), 127);
- r_timeout_on = TRUE;
- } while ( n_io );
-
- ASS_RET((!MemCmp(buf, buf1, sizeof(buf))), 120);
- }
-
- return 0;
-}
-
-
-static Int2 TEST__server_2(SOCK sock, LSOCK lsock)
-{ /* reserved ret.codes [220-229] */
- ESOCK_ErrCode err_code;
- Uint4 n_io, n_io_done;
- char buf[TEST_BUFSIZE];
- STimeout r_to, w_to;
- Uint4 i;
-
- ErrPostEx(SEV_INFO, SOCK_ERRCODE, 220, "TS2()");
-
- r_to.sec = 0;
- r_to.usec = 0;
- w_to = r_to;
-
- /* goto */
- l_reconnect: /* reconnection loopback */
-
- err_code = SOCK_SetTimeout(sock, eSOCK_OnRead, &r_to, 0, 0);
- ASS_RET((err_code == eSOCK_ESuccess), 220);
- err_code = SOCK_SetTimeout(sock, eSOCK_OnWrite, &w_to, 0, 0);
- ASS_RET((err_code == eSOCK_ESuccess), 221);
-
- for (i = 0; ; i++) {
- char* x_buf;
-
- /* read data from socket */
- n_io = sizeof(buf);
- err_code = SOCK_Read(sock, buf, n_io, &n_io_done);
- switch ( err_code )
- {
- case eSOCK_ESuccess:
- ErrPostEx(SEV_INFO, SOCK_ERRCODE, 222,
- "TS2:read:[%lu], err_code=%d, n_io=%5lu, n_io_done=%5lu",
- (unsigned long)i, (int)err_code,
- (unsigned long)n_io, (unsigned long)n_io_done);
- ASS_RET((n_io_done > 0), 222);
- break;
-
- case eSOCK_EClosed:
- ErrPostEx(SEV_INFO, SOCK_ERRCODE, 223,
- "TS2:read: connection closed");
- ASSERT( SOCK_Eof(sock) );
-
- /* reconnect */
- if ( !lsock )
- return 0;
-
- ErrPostEx(SEV_INFO, SOCK_ERRCODE, 223, "TS2:reconnect");
- SOCK_Close(sock);
- err_code = LSOCK_Accept(lsock, NULL, &sock);
- ASS_RET((err_code == eSOCK_ESuccess), 229);
- ASSERT( !SOCK_Eof(sock) );
- /* !!! */
- goto l_reconnect;
-
- case eSOCK_ETimeout:
- ErrPostEx(SEV_INFO, SOCK_ERRCODE, 224,
- "TS2:read:[%lu] timeout expired: %5lu sec, %6lu msec",
- (unsigned long)i,
- (unsigned long)r_to.sec, (unsigned long)r_to.usec);
- ASS_RET((n_io_done == 0), 224);
- s_DoubleTimeout(&r_to);
- err_code = SOCK_SetTimeout(sock, eSOCK_OnRead, &r_to, 0, 0);
- ASS_RET((err_code == eSOCK_ESuccess), 225);
- ASSERT( !SOCK_Eof(sock) );
- break;
-
- default:
- ASS_RET(0, 226);
- }
-
- /* write(just the same) data back to client */
- n_io = n_io_done;
- x_buf = buf;
- while ( n_io ) {
- err_code = SOCK_Write(sock, buf, n_io, &n_io_done);
- switch ( err_code )
- {
- case eSOCK_ESuccess:
- ErrPostEx(SEV_INFO, SOCK_ERRCODE, 231,
- "TS2:write:[%lu], err_code=%d, n_io=%5lu, n_io_done=%5lu",
- (unsigned long)i, (int)err_code,
- (unsigned long)n_io, (unsigned long)n_io_done);
- ASS_RET((n_io_done > 0), 231);
- break;
- case eSOCK_EClosed:
- ErrPostEx(SEV_ERROR, SOCK_ERRCODE, 232,
- "TS2:write: connection closed");
- return 230;
- case eSOCK_ETimeout:
- ErrPostEx(SEV_INFO, SOCK_ERRCODE, 233,
- "TS2:write:[%lu] timeout expired: %5lu sec, %6lu msec",
- (unsigned long)i,
- (unsigned long)w_to.sec, (unsigned long)w_to.usec);
- ASS_RET((n_io_done == 0), 233);
- s_DoubleTimeout(&w_to);
- err_code = SOCK_SetTimeout(sock, eSOCK_OnWrite, &w_to, 0, 0);
- ASS_RET((err_code == eSOCK_ESuccess), 234);
- break;
- default:
- ASS_RET(0, 235);
- }
-
- n_io -= n_io_done;
- x_buf += n_io_done;
- }
- }
-
- return 0;
-}
-
-
-/* Skeletons for the socket i/o test:
- * TEST__client(...)
- * TEST__server(...)
- * establish and close connection; call test i/o functions like
- * TEST__[client|server]_[1|2|...] (...)
- */
-static Int2 TEST__client(const char* server_host,
- Uint2 server_port,
- const STimeout* timeout)
-{ /* reserved ret.codes [100-109] */
- SOCK sock;
- ESOCK_ErrCode err_code;
- Int2 ret_code;
-
- ErrPostEx(SEV_INFO, SOCK_ERRCODE, 101,
- "TEST__client(host = \"%s\", port = %u)",
- server_host, (unsigned)server_port);
-
- /* Connect to server */
- err_code = SOCK_Create(server_host, server_port, timeout, &sock);
- ASS_RET((err_code == eSOCK_ESuccess), 100);
-
- /* Test the simplest randezvous(plain request-reply)
- * The two peer functions are:
- * "TEST__[client|server]_1(SOCK sock)"
- */
- ret_code = TEST__client_1(sock);
- ASS_RET((ret_code == 0), 101);
-
- /* Test a more complex case
- * The two peer functions are:
- * "TEST__[client|server]_2(SOCK sock)"
- */
- ret_code = TEST__client_2(sock);
- ASS_RET((ret_code == 0), 102);
-
- /* Close connection and exit */
- err_code = SOCK_Close(sock);
- ASS_RET((err_code == eSOCK_ESuccess || err_code == eSOCK_EClosed), 109);
- return 0;
-}
-
-
-static Int2 TEST__server(Uint2 port)
-{ /* reserved ret.codes [200-209] */
- LSOCK lsock;
- ESOCK_ErrCode err_code;
-
- ErrPostEx(SEV_INFO, SOCK_ERRCODE, 201,
- "TEST__server(port = %u)", (unsigned)port);
-
- /* Create listening socket */
- err_code = LSOCK_Create(port, 1, &lsock);
- ASS_RET((err_code == eSOCK_ESuccess), 200);
-
- /* Accept connections from clients and run test sessions */
- for (;;)
- {
- Int2 ret_code;
-
- /* Accept connection */
- SOCK sock;
- err_code = LSOCK_Accept(lsock, NULL, &sock);
- ASS_RET((err_code == eSOCK_ESuccess), 208);
-
- /* Test the simplest randezvous(plain request-reply)
- * The two peer functions are:
- * "TEST__[client|server]_1(SOCK sock)"
- */
- ret_code = TEST__server_1(sock);
- ASS_RET((ret_code == 0), 201);
-
- /* Test a more complex case
- * The two peer functions are:
- * "TEST__[client|server]_2(SOCK sock)"
- */
-#ifdef DO_RECONNECT
- ret_code = TEST__server_2(sock, lsock);
-#else
- ret_code = TEST__server_2(sock, 0);
-#endif
- ASS_RET((ret_code == 0), 202);
-
- /* Close connection */
- err_code = SOCK_Close(sock);
- ASS_RET((err_code == eSOCK_ESuccess || err_code == eSOCK_EClosed), 209);
-
-#ifdef TEST_SRV1_ONCE
- /* finish after the first session */
- break;
-#endif
- }
-
- /* Close listening socket */
- err_code = LSOCK_Close(lsock);
- ASS_RET((err_code == eSOCK_ESuccess), 204);
- return 0;
-}
-
-
-/* Main function
- * Parse command-line options, initialize and cleanup API internals;
- * run client or server test
- */
-extern Int2 Main(void)
-{
-#define MIN_PORT 5001
- Int4 argc = GetArgc();
- char** argv = GetArgv();
-
- ErrSetOpts(ERR_TEE, ERR_LOG_ON);
- ErrSetLogLevel(SEV_INFO);
- ErrSetMessageLevel(SEV_INFO);
- VERIFY ( ErrSetLog("ncbisock.log") );
-
- {{
- char local_host[64];
- VERIFY ( GetHostName(local_host, sizeof(local_host)) );
- ErrPostEx(SEV_INFO, SOCK_ERRCODE, 200,
- "\nRunning NCBISOCK test on host \"%s\"", local_host);
- }}
-
-#ifdef DO_SERVER
- argc = 2;
-#endif
-#ifdef DO_CLIENT
- argc = 3;
-#endif
-
- switch ( argc )
- {
- case 2:
- { /* Server */
-#ifdef DO_SERVER
- short port = 5555;
-#else
- short port;
- if (sscanf(argv[1], "%hd", &port) != 1 ||
- port < MIN_PORT)
- break;
-#endif
- ErrPostEx(SEV_INFO, SOCK_ERRCODE, 200,
- "Starting NCBISOCK server test...");
- VERIFY ( ErrSetLog("ncbisock.srv") );
-
- {{
- Int2 ret_code = TEST__server((Uint2)port);
- VERIFY ( SOCK_Destroy() == eSOCK_ESuccess );
- return ret_code;
- }}
- }
-
- case 3:
- case 4:
- { /* Client */
- STimeout* timeout = 0;
- STimeout x_timeout;
-#ifdef DO_CLIENT
- char* server_host = "localhost";
- short server_port = 5555;
- x_timeout.sec = x_timeout.usec = 999999;
-#else
- /* host */
- char* server_host = argv[1];
-
- /* port */
- short server_port;
- if (sscanf(argv[2], "%hd", &server_port) != 1 ||
- server_port < MIN_PORT)
- break;
-
- /* timeout */
- if (argc == 4) {
- double tm_out = atof(argv[3]);
- if (tm_out < 0)
- break;
- x_timeout.sec = (Uint4) tm_out;
- x_timeout.usec = (Uint4) ((tm_out - x_timeout.sec) * 1000000);
- timeout = &x_timeout;
- } else {
- x_timeout.sec = x_timeout.usec = 999999;
- }
-#endif
- ErrPostEx(SEV_INFO, SOCK_ERRCODE, 100,
- "Starting NCBISOCK client test...\n"
- "%s:%d, timeout=%lu.%06lu\n",
- server_host, (int)server_port,
- (unsigned long)x_timeout.sec, (unsigned long)x_timeout.usec);
- VERIFY ( ErrSetLog("ncbisock.cli") );
-
- {{
- Int2 ret_code = TEST__client(server_host, (Uint2)server_port,
- timeout);
- VERIFY ( SOCK_Destroy() == eSOCK_ESuccess );
- return ret_code;
- }}
- }
- }
-
- /* Bad cmd-line arguments; Usage */
- ErrPostEx(SEV_ERROR, SOCK_ERRCODE, 666,
- "Usage:\n"
- " Client: %s <srv_host> <port> [conn_timeout]\n"
- " Server: %s <port>\n"
- " where <port> not less than %hd, and [conn_timeout] is double",
- argv[0], argv[0], (short)MIN_PORT);
- return 1;
-}