test_ncbi_dsock.c
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:14k
- /*
- * ===========================================================================
- * PRODUCTION $Log: test_ncbi_dsock.c,v $
- * PRODUCTION Revision 1000.1 2004/02/12 21:56:23 gouriano
- * PRODUCTION PRODUCTION: UPGRADED [CORE_001] Dev-tree R6.14
- * PRODUCTION
- * ===========================================================================
- */
- /* $Id: test_ncbi_dsock.c,v 1000.1 2004/02/12 21:56:23 gouriano 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 suite for datagram socket API
- *
- */
- #include "../ncbi_ansi_ext.h"
- #include "../ncbi_priv.h" /* CORE logging facilities */
- #include <connect/ncbi_connutil.h>
- #include <connect/ncbi_socket.h>
- #include <errno.h>
- #include <stdlib.h>
- #include <time.h>
- #ifdef NCBI_OS_UNIX
- # include <unistd.h>
- #endif /*NCBI_OS_UNIX*/
- /* This header must go last */
- #include "test_assert.h"
- #if defined(NCBI_OS_BSD) || defined(NCBI_OS_OSF1) || defined(NCBI_OS_DARWIN)
- /* FreeBSD has this limit :-/ Source: `sysctl net.inet.udp.maxdgram` */
- /* For OSF1 (and FreeBSD) see also: /usr/include/netinet/udp_var.h */
- # define MAX_DGRAM_SIZE (9*1024)
- #elif defined(NCBI_OS_IRIX)
- /* This has been found experimentally on IRIX64 6.5 04101931 IP25 */
- # define MAX_DGRAM_SIZE (60*1024)
- #elif defined(NCBI_OS_LINUX)
- /* Larger sizes do not seem to work everywhere */
- # define MAX_DGRAM_SIZE 65000
- #else
- /* This is the maximal datagram size defined by the UDP standard */
- # define MAX_DGRAM_SIZE 65535
- #endif
- #define DEFAULT_PORT 55555
- static int s_Usage(const char* prog)
- {
- CORE_LOGF(eLOG_Error, ("Usage:n%s {client|server} [port [seed]]", prog));
- return 1;
- }
- static int s_Server(int x_port)
- {
- char addr[32];
- char* buf;
- SOCK server;
- EIO_Status status;
- STimeout timeout;
- unsigned int peeraddr;
- unsigned short peerport, port;
- size_t msglen, n, len;
- char minibuf[255];
- if (x_port <= 0) {
- CORE_LOG(eLOG_Error, "[Server] Port wrongly specified");
- return 1;
- }
- port = (unsigned short) x_port;
- CORE_LOGF(eLOG_Note, ("[Server] Opening DSOCK on port %hu", port));
- if ((status = DSOCK_Create(&server)) != eIO_Success) {
- CORE_LOGF(eLOG_Error, ("[Server] Error creating DSOCK: %s",
- IO_StatusStr(status)));
- return 1;
- }
- if ((status = DSOCK_Bind(server, port)) != eIO_Success) {
- CORE_LOGF(eLOG_Error, ("[Server] Error binding DSOCK to port %hu: %s",
- port, IO_StatusStr(status)));
- return 1;
- }
- for (;;) {
- if ((status = DSOCK_WaitMsg(server, 0/*infinite*/)) != eIO_Success) {
- CORE_LOGF(eLOG_Error, ("[Server] Error waiting on DSOCK: %s",
- IO_StatusStr(status)));
- break;
- }
- timeout.sec = 0;
- timeout.usec = 0;
- if ((status = SOCK_SetTimeout(server, eIO_Read, &timeout))
- != eIO_Success) {
- CORE_LOGF(eLOG_Error, ("[Server] Error setting zero read tmo: %s",
- IO_StatusStr(status)));
- break;
- }
- len = (size_t)(((double) rand()/(double) RAND_MAX)*sizeof(minibuf));
- if ((status = DSOCK_RecvMsg(server, minibuf, len, 0, &msglen,
- &peeraddr, &peerport)) != eIO_Success) {
- CORE_LOGF(eLOG_Error, ("[Server] Error reading from DSOCK: %s",
- IO_StatusStr(status)));
- continue;
- }
- if (len > msglen)
- len = msglen;
- if (SOCK_ntoa(peeraddr, addr, sizeof(addr)) != 0)
- strcpy(addr, "<unknown>");
- CORE_LOGF(eLOG_Note, ("[Server] Message received from %s:%hu, "
- "%lu bytes",
- addr, peerport, (unsigned long) msglen));
- if (!(buf = (char*) malloc(msglen ? msglen : 1))) {
- CORE_LOG_ERRNO(eLOG_Error, errno,"[Server] Cannot alloc msg buf");
- break;
- }
- if (len)
- memcpy(buf, minibuf, len);
- while (len < msglen) {
- n = (size_t)(((double)rand()/(double)RAND_MAX)*(msglen-len) + 0.5);
- if ((status = SOCK_Read(server, buf + len, n, &n, eIO_ReadPlain))
- != eIO_Success) {
- CORE_LOGF(eLOG_Error,("[Server] Error reading msg @ byte %lu:"
- " %s", (unsigned long) len,
- IO_StatusStr(status)));
- free(buf);
- continue;
- }
- len += n;
- }
- assert(SOCK_Read(server, 0, 1, &n, eIO_ReadPlain) == eIO_Closed);
- CORE_LOG(eLOG_Note, "[Server] Bouncing the message to sender");
- timeout.sec = 1;
- timeout.usec = 0;
- if ((status = SOCK_SetTimeout(server, eIO_Write, &timeout))
- != eIO_Success){
- CORE_LOGF(eLOG_Error, ("[Server] Error setting write tmo: %s",
- IO_StatusStr(status)));
- break;
- }
- for (len = 0; len < msglen; len += n) {
- n = (size_t)(((double)rand()/(double)RAND_MAX)*(msglen-len) + 0.5);
- if ((status = SOCK_Write(server, buf + len, n, &n, eIO_WritePlain))
- != eIO_Success) {
- CORE_LOGF(eLOG_Error,("[Server] Error writing msg @ byte %lu:"
- " %s", (unsigned long) len,
- IO_StatusStr(status)));
- break;
- }
- }
- free(buf);
- if ((status = DSOCK_SendMsg(server, addr, peerport, "--Reply--", 9))
- != eIO_Success) {
- CORE_LOGF(eLOG_Error, ("[Server] Error sending to DSOCK: %s",
- IO_StatusStr(status)));
- /*continue*/;
- }
- }
- /* On errors control reaches here */
- if ((status = SOCK_Close(server)) != eIO_Success) {
- CORE_LOGF(eLOG_Error, ("[Server] Error closing DSOCK: %s",
- IO_StatusStr(status)));
- }
- return 1;
- }
- static int s_Client(int x_port, unsigned int max_try)
- {
- size_t msglen, n;
- STimeout timeout;
- EIO_Status status;
- SOCK client;
- unsigned short port;
- char* buf;
- unsigned long id;
- unsigned int m;
- if (x_port <= 0) {
- CORE_LOG(eLOG_Error, "[Client] Port wrongly specified");
- return 1;
- }
-
- port = (unsigned short) x_port;
- CORE_LOGF(eLOG_Note, ("[Client] Opening DSOCK on port %hu", port));
- if ((status = DSOCK_Create(&client)) != eIO_Success) {
- CORE_LOGF(eLOG_Error, ("[Client] Error creating DSOCK: %s",
- IO_StatusStr(status)));
- return 1;
- }
- msglen = (size_t)(((double)rand()/(double)RAND_MAX)*(MAX_DGRAM_SIZE - 10));
- if (msglen < sizeof(time_t))
- msglen = sizeof(time_t);
- CORE_LOGF(eLOG_Note, ("[Client] Generating a message %lu bytes long",
- (unsigned long) msglen));
- if (!(buf = (char*) malloc(2*msglen + 9))) {
- CORE_LOG_ERRNO(eLOG_Error, errno, "[Client] Cannot alloc msg buf");
- return 1;
- }
- for (n = sizeof(unsigned long); n < msglen; n++)
- buf[n] = rand() % 0xFF;
- id = (unsigned long) time(0);
- for (m = 1; m <= max_try; m++) {
- unsigned long tmp;
- if (m != 1)
- CORE_LOGF(eLOG_Note, ("[Client] Attempt #%u", (unsigned int) m));
- id++;
- *((unsigned long*) buf) = SOCK_htonl((unsigned long) id);
- if ((status = DSOCK_SendMsg(client, "127.0.0.1", port, buf, msglen))
- != eIO_Success) {
- CORE_LOGF(eLOG_Error, ("[Client] Error sending to DSOCK: %s",
- IO_StatusStr(status)));
- return 1;
- }
- timeout.sec = 1;
- timeout.usec = 0;
- if ((status = SOCK_SetTimeout(client, eIO_Read, &timeout))
- != eIO_Success) {
- CORE_LOGF(eLOG_Error, ("[Client] Error setting read timeout: %s",
- IO_StatusStr(status)));
- return 1;
- }
- again:
- if ((status = DSOCK_RecvMsg(client, &buf[msglen], msglen+9,0, &n, 0,0))
- != eIO_Success) {
- CORE_LOGF(eLOG_Error, ("[Client] Error reading from DSOCK: %s",
- IO_StatusStr(status)));
- continue;
- }
- if (n != msglen + 9) {
- CORE_LOGF(eLOG_Error, ("[Client] Received message of wrong size: "
- "%lu", (unsigned long) n));
- return 1;
- }
- memcpy(&tmp, &buf[msglen], sizeof(tmp));
- if (SOCK_ntohl(tmp) != id) {
- m++;
- CORE_LOGF(m < max_try ? eLOG_Warning : eLOG_Error,
- ("[Client] Stale message received%s",
- m <= max_try ? ", reattempting to fetch" : ""));
- if (m <= max_try)
- goto again;
- break;
- }
- CORE_LOGF(eLOG_Note, ("[Client] Received the message back, %lu bytes",
- (unsigned long) n));
- assert(SOCK_Read(client, 0, 1, &n, eIO_ReadPlain) == eIO_Closed);
- break;
- }
- if (m > max_try)
- return 1;
- for (n = sizeof(unsigned long); n < msglen; n++) {
- if (buf[n] != buf[msglen + n])
- break;
- }
- if (n < msglen) {
- CORE_LOGF(eLOG_Error, ("[Client] Bounced message corrupted, off=%lu",
- (unsigned long) n));
- return 1;
- }
- if (strncmp(&buf[msglen*2], "--Reply--", 9) != 0) {
- CORE_LOGF(eLOG_Error, ("[Client] No signature in the message: %.9s",
- &buf[msglen*2]));
- return 1;
- }
- free(buf);
- if ((status = SOCK_Close(client)) != eIO_Success) {
- CORE_LOGF(eLOG_Error, ("[Client] Error closing DSOCK: %s",
- IO_StatusStr(status)));
- return 1;
- }
- CORE_LOG(eLOG_Note, "[Client] Completed successfully");
- return 0;
- }
- int main(int argc, const char* argv[])
- {
- unsigned long seed;
- unsigned int max_try = DEF_CONN_MAX_TRY;
- const char* env = getenv("CONN_DEBUG_PRINTOUT");
- CORE_SetLOGFormatFlags(fLOG_None | fLOG_Level |
- fLOG_OmitNoteLevel | fLOG_DateTime);
- CORE_SetLOGFILE(stderr, 0/*false*/);
- if (argc < 2 || argc > 4)
- return s_Usage(argv[0]);
- if (argc <= 3) {
- #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);
- CORE_LOGF(eLOG_Note, ("Random SEED = %lu", seed));
- srand(seed);
- if (env && (strcasecmp(env, "1") == 0 ||
- strcasecmp(env, "yes") == 0 ||
- strcasecmp(env, "true") == 0 ||
- strcasecmp(env, "some") == 0 ||
- strcasecmp(env, "data") == 0)) {
- SOCK_SetDataLoggingAPI(eOn);
- }
- if (!(env = getenv("CONN_MAX_TRY")) || !(max_try = atoi(env)))
- max_try = DEF_CONN_MAX_TRY;
- if (strcasecmp(argv[1], "client") == 0)
- return s_Client(argv[2] ? atoi(argv[2]) : DEFAULT_PORT, max_try);
- if (strcasecmp(argv[1], "server") == 0)
- return s_Server(argv[2] ? atoi(argv[2]) : DEFAULT_PORT);
- return s_Usage(argv[0]);
- }
- /*
- * --------------------------------------------------------------------------
- * $Log: test_ncbi_dsock.c,v $
- * Revision 1000.1 2004/02/12 21:56:23 gouriano
- * PRODUCTION: UPGRADED [CORE_001] Dev-tree R6.14
- *
- * Revision 6.14 2003/12/11 15:34:29 lavr
- * Lower maximal datagram size for Linux - 65535 didn't seem to work everywhere
- *
- * Revision 6.13 2003/12/10 17:24:16 lavr
- * Reattempt to send/receive a datagram on I/O errors in client
- *
- * Revision 6.12 2003/10/27 19:00:32 lavr
- * Limit datagram size for Darwin (which is BSD based)
- *
- * Revision 6.11 2003/05/29 18:03:06 lavr
- * Changed one client's message
- *
- * Revision 6.10 2003/05/14 03:58:43 lavr
- * Match changes in respective APIs of the tests
- *
- * Revision 6.9 2003/04/30 17:04:01 lavr
- * Conformance to slightly modified datagram socket API
- *
- * Revision 6.8 2003/03/25 15:07:21 lavr
- * Protect macros' values by enclosing in parentheses
- *
- * Revision 6.7 2003/03/25 15:04:13 lavr
- * Add IRIX-specific datagram size limit (60K)
- *
- * Revision 6.6 2003/02/28 14:46:36 lavr
- * Explicit casts for malloc()'ed memory
- *
- * Revision 6.5 2003/02/14 15:41:26 lavr
- * Limit packet size on OSF1, too
- *
- * Revision 6.4 2003/02/06 04:34:28 lavr
- * Do not exceed maximal dgram size on BSD; trickier readout in s_Server()
- *
- * Revision 6.3 2003/02/04 22:04:47 lavr
- * Protection from truncation to 0 in double->int conversion
- *
- * Revision 6.2 2003/01/17 01:26:44 lavr
- * Test improved/extended
- *
- * Revision 6.1 2003/01/16 16:33:06 lavr
- * Initial revision
- *
- * ==========================================================================
- */