nsprpub/pr/tests/writev.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/nsprpub/pr/tests/writev.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,197 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "nspr.h"
    1.10 +
    1.11 +#include "plgetopt.h"
    1.12 +
    1.13 +#include <stdlib.h>
    1.14 +#include <string.h>
    1.15 +
    1.16 +
    1.17 +#ifndef IOV_MAX
    1.18 +#define IOV_MAX 16
    1.19 +#endif
    1.20 +
    1.21 +#define BASE_PORT 9867
    1.22 +
    1.23 +int PR_CALLBACK Writev(int argc, char **argv)
    1.24 +{
    1.25 +
    1.26 +    PRStatus rv;
    1.27 +    PRNetAddr serverAddr;
    1.28 +    PRFileDesc *clientSock, *debug = NULL;
    1.29 +
    1.30 +    char *buffer = NULL;
    1.31 +    PRIOVec *iov = NULL;
    1.32 +    PRBool passed = PR_TRUE;
    1.33 +    PRIntervalTime timein, elapsed, timeout;
    1.34 +    PRIntervalTime tmo_min = 0x7fffffff, tmo_max = 0, tmo_elapsed = 0;
    1.35 +    PRInt32 tmo_counted = 0, iov_index, loop, bytes, number_fragments;
    1.36 +    PRInt32 message_length = 100, fragment_length = 100, messages = 100;
    1.37 +    struct Descriptor { PRInt32 length; PRUint32 checksum; } descriptor;
    1.38 +
    1.39 +    /*
    1.40 +     * USAGE
    1.41 +     * -h       dns name of host serving the connection (default = self)
    1.42 +     * -m       number of messages to send              (default = 100)
    1.43 +     * -s       size of each message                    (default = 100)
    1.44 +     * -f       size of each message fragment           (default = 100)
    1.45 +     */
    1.46 +
    1.47 +	PLOptStatus os;
    1.48 +	PLOptState *opt = PL_CreateOptState(argc, argv, "dh:m:s:f:");
    1.49 +
    1.50 +    PR_STDIO_INIT();
    1.51 +    rv = PR_InitializeNetAddr(PR_IpAddrLoopback, BASE_PORT, &serverAddr);
    1.52 +    PR_ASSERT(PR_SUCCESS == rv);
    1.53 +
    1.54 +	while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
    1.55 +    {
    1.56 +        if (PL_OPT_BAD == os) continue;
    1.57 +        switch (opt->option)
    1.58 +        {
    1.59 +        case 'h':  /* the remote host */
    1.60 +            {
    1.61 +                PRIntn es = 0;
    1.62 +                PRHostEnt host;
    1.63 +                char buffer[1024];
    1.64 +                (void)PR_GetHostByName(opt->value, buffer, sizeof(buffer), &host);
    1.65 +                es = PR_EnumerateHostEnt(es, &host, BASE_PORT, &serverAddr);
    1.66 +                PR_ASSERT(es > 0);
    1.67 +            }
    1.68 +            break;
    1.69 +        case 'd':  /* debug mode */
    1.70 +            debug = PR_GetSpecialFD(PR_StandardError);
    1.71 +            break;
    1.72 +        case 'm':  /* number of messages to send */
    1.73 +            messages = atoi(opt->value);
    1.74 +            break;
    1.75 +        case 's':  /* total size of each message */
    1.76 +            message_length = atoi(opt->value);
    1.77 +            break;
    1.78 +        case 'f':  /* size of each message fragment */
    1.79 +            fragment_length = atoi(opt->value);
    1.80 +            break;
    1.81 +        default:
    1.82 +            break;
    1.83 +        }
    1.84 +    }
    1.85 +	PL_DestroyOptState(opt);
    1.86 +
    1.87 +    buffer = (char*)malloc(message_length);
    1.88 +
    1.89 +    number_fragments = (message_length + fragment_length - 1) / fragment_length + 1;
    1.90 +    while (IOV_MAX < number_fragments)
    1.91 +    {
    1.92 +        fragment_length = message_length / (IOV_MAX - 2);
    1.93 +        number_fragments = (message_length + fragment_length - 1) /
    1.94 +            fragment_length + 1;
    1.95 +        if (NULL != debug) PR_fprintf(debug, 
    1.96 +            "Too many fragments - reset fragment length to %ld\n", fragment_length);
    1.97 +    }
    1.98 +    iov = (PRIOVec*)malloc(number_fragments * sizeof(PRIOVec));
    1.99 +
   1.100 +    iov[0].iov_base = (char*)&descriptor;
   1.101 +    iov[0].iov_len = sizeof(descriptor);
   1.102 +    for (iov_index = 1; iov_index < number_fragments; ++iov_index)
   1.103 +    {
   1.104 +        iov[iov_index].iov_base = buffer + (iov_index - 1) * fragment_length;
   1.105 +        iov[iov_index].iov_len = fragment_length;
   1.106 +    }
   1.107 +
   1.108 +    for (bytes = 0; bytes < message_length; ++bytes)
   1.109 +        buffer[bytes] = (char)bytes;
   1.110 +
   1.111 +    timeout = PR_SecondsToInterval(1);
   1.112 +
   1.113 +    for (loop = 0; loop < messages; ++loop)
   1.114 +    {
   1.115 +        if (NULL != debug)
   1.116 +            PR_fprintf(debug, "[%d]socket ... ", loop);
   1.117 +        clientSock = PR_NewTCPSocket();
   1.118 +        if (clientSock)
   1.119 +        {
   1.120 +            timein = PR_IntervalNow();
   1.121 +            if (NULL != debug)
   1.122 +                PR_fprintf(debug, "connecting ... ");
   1.123 +            rv = PR_Connect(clientSock, &serverAddr, timeout);
   1.124 +            if (PR_SUCCESS == rv)
   1.125 +            {
   1.126 +                descriptor.checksum = 0;
   1.127 +                descriptor.length = (loop < (messages - 1)) ? message_length : 0;
   1.128 +                if (0 == descriptor.length) number_fragments = 1;
   1.129 +                else
   1.130 +                    for (iov_index = 0; iov_index < descriptor.length; ++iov_index)
   1.131 +                    {
   1.132 +                        PRUint32 overflow = descriptor.checksum & 0x80000000;
   1.133 +                        descriptor.checksum = (descriptor.checksum << 1);
   1.134 +                        if (0x00000000 != overflow) descriptor.checksum += 1;
   1.135 +                        descriptor.checksum += buffer[iov_index];
   1.136 +                    }
   1.137 +                if (NULL != debug) PR_fprintf(
   1.138 +                    debug, "sending %d bytes ... ", descriptor.length);
   1.139 +
   1.140 +                /* then, at the last moment ... */
   1.141 +                descriptor.length = PR_ntohl(descriptor.length);
   1.142 +                descriptor.checksum = PR_ntohl(descriptor.checksum);
   1.143 +
   1.144 +                bytes = PR_Writev(clientSock, iov, number_fragments, timeout);
   1.145 +                if (NULL != debug)
   1.146 +                    PR_fprintf(debug, "closing ... ");
   1.147 +                rv = PR_Shutdown(clientSock, PR_SHUTDOWN_BOTH);
   1.148 +                rv = PR_Close(clientSock);
   1.149 +                if (NULL != debug) PR_fprintf(
   1.150 +                    debug, "%s\n", ((PR_SUCCESS == rv) ? "good" : "bad"));
   1.151 +                elapsed = PR_IntervalNow() - timein;
   1.152 +                if (elapsed < tmo_min) tmo_min = elapsed;
   1.153 +                else if (elapsed > tmo_max) tmo_max = elapsed;
   1.154 +                tmo_elapsed += elapsed;
   1.155 +                tmo_counted += 1;
   1.156 +            }
   1.157 +            else
   1.158 +            {
   1.159 +                if (NULL != debug) PR_fprintf(
   1.160 +                    debug, "failed - retrying (%d, %d)\n",
   1.161 +                    PR_GetError(), PR_GetOSError());
   1.162 +                PR_Close(clientSock);
   1.163 +            }
   1.164 +        }
   1.165 +        else if (NULL != debug)
   1.166 +        {
   1.167 +            PR_fprintf(debug, "unable to create client socket\n");
   1.168 +            passed = PR_FALSE;
   1.169 +        }
   1.170 +    }
   1.171 +    if (NULL != debug) {
   1.172 +        if (0 == tmo_counted) {
   1.173 +            PR_fprintf(debug, "No connection made\n");
   1.174 +        } else {
   1.175 +        PR_fprintf(
   1.176 +            debug, "\nTimings: %d [%d] %d (microseconds)\n",
   1.177 +            PR_IntervalToMicroseconds(tmo_min),
   1.178 +            PR_IntervalToMicroseconds(tmo_elapsed / tmo_counted),
   1.179 +            PR_IntervalToMicroseconds(tmo_max));
   1.180 +	}
   1.181 +    }
   1.182 +
   1.183 +    PR_DELETE(buffer);
   1.184 +    PR_DELETE(iov);
   1.185 +
   1.186 +    PR_fprintf(
   1.187 +        PR_GetSpecialFD(PR_StandardError),
   1.188 +        "%s\n", (passed) ? "PASSED" : "FAILED");
   1.189 +    return (passed) ? 0 : 1;
   1.190 +}
   1.191 +
   1.192 +int main(int argc, char **argv)
   1.193 +{
   1.194 +    return (PR_VersionCheck(PR_VERSION)) ?
   1.195 +        PR_Initialize(Writev, argc, argv, 4) : -1;
   1.196 +}  /* main */
   1.197 +
   1.198 +/* writev.c */
   1.199 +
   1.200 +

mercurial