Home | History | Annotate | Download | only in auxprogs
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- A simple debuginfo server for Valgrind.                      ---*/
      4 /*---                                         valgrind-di-server.c ---*/
      5 /*--------------------------------------------------------------------*/
      6 
      7 /* To build for an x86_64-linux host:
      8       gcc -g -Wall -O -o valgrind-di-server \
      9          auxprogs/valgrind-di-server.c -Icoregrind -Iinclude \
     10          -IVEX/pub -DVGO_linux -DVGA_amd64
     11 
     12    To build for an x86 (32-bit) host
     13       The same, except change -DVGA_amd64 to -DVGA_x86
     14 */
     15 
     16 /*
     17    This file is part of Valgrind, a dynamic binary instrumentation
     18    framework.
     19 
     20    Copyright (C) 2013-2017 Mozilla Foundation
     21 
     22    This program is free software; you can redistribute it and/or
     23    modify it under the terms of the GNU General Public License as
     24    published by the Free Software Foundation; either version 2 of the
     25    License, or (at your option) any later version.
     26 
     27    This program is distributed in the hope that it will be useful, but
     28    WITHOUT ANY WARRANTY; without even the implied warranty of
     29    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     30    General Public License for more details.
     31 
     32    You should have received a copy of the GNU General Public License
     33    along with this program; if not, write to the Free Software
     34    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     35    02111-1307, USA.
     36 
     37    The GNU General Public License is contained in the file COPYING.
     38 */
     39 
     40 /* Contributed by Julian Seward <jseward (at) acm.org> */
     41 
     42 /* This code works (just), but it's a mess.  Cleanups (also for
     43    coregrind/m_debuginfo/image.c):
     44 
     45    * Build this file for the host arch, not the target.  But how?
     46      Even Tromey had difficulty figuring out how to do that.
     47 
     48    * Change the use of pread w/ fd to FILE*, for the file we're
     49      serving.  Or, at least, put a loop around the pread uses
     50      so that it works correctly in the case where pread reads more
     51      than zero but less than we asked for.
     52 
     53    * CRC3 request/response: pass session-IDs back and forth and
     54      check them
     55 
     56    * Check that all error cases result in a FAIL frame being returned.
     57 
     58    * image.c: don't assert in cases where a FAIL frame is returned;
     59      instead cause the debuginfo reading to fail gracefully.  (Not
     60      sure how to do this)
     61 
     62    * Improve diagnostic printing
     63 
     64    * image.c: do we need to do VG_(write_socket) ?  Will it work
     65      just to use ordinary VG_(write) ?
     66 
     67    * Both files: document the reason for setting TCP_NODELAY
     68 
     69    * Add a command line argument saying where the served-from
     70      directory is -- changes clo_serverpath.
     71 
     72    * Fix up (common up) massive code duplication between client and
     73      server.
     74 
     75    * Tidy up the LZO source files; integrate properly in the build
     76      system.
     77 */
     78 
     79 /*---------------------------------------------------------------*/
     80 
     81 /* Include valgrind headers before system headers to avoid problems
     82    with the system headers #defining things which are used as names
     83    of structure members in vki headers. */
     84 
     85 #include "pub_core_basics.h"
     86 #include "pub_core_libcassert.h"    // For VG_BUGS_TO
     87 #include "pub_core_vki.h"           // Avoids warnings from
     88                                     // pub_core_libcfile.h
     89 #include "pub_core_libcfile.h"      // For VG_CLO_DEFAULT_LOGPORT
     90 
     91 /* Needed to get a definition for pread() from unistd.h */
     92 #ifndef _XOPEN_SOURCE
     93 #define _XOPEN_SOURCE 600
     94 #endif
     95 
     96 #include <stdio.h>
     97 #include <unistd.h>
     98 #include <string.h>
     99 #include <time.h>
    100 #include <fcntl.h>
    101 #include <stdlib.h>
    102 #include <signal.h>
    103 #include <sys/poll.h>
    104 #include <sys/types.h>
    105 #include <sys/socket.h>
    106 #include <netinet/in.h>
    107 #include <sys/stat.h>
    108 #include <netinet/tcp.h>
    109 
    110 #include "../coregrind/m_debuginfo/minilzo.h"
    111 
    112 /*---------------------------------------------------------------*/
    113 
    114 /* The default allowable number of concurrent connections. */
    115 #define  M_CONNECTIONS_DEFAULT 50
    116 /* The maximum allowable number of concurrent connections. */
    117 #define  M_CONNECTIONS_MAX     5000
    118 
    119 /* The maximum allowable number of concurrent connections. */
    120 unsigned M_CONNECTIONS = 0;
    121 
    122 static const char* clo_serverpath = ".";
    123 
    124 
    125 /*---------------------------------------------------------------*/
    126 
    127 __attribute__ ((noreturn))
    128 static void panic ( const char* str )
    129 {
    130    fprintf(stderr,
    131            "\nvalgrind-di-server: the "
    132            "'impossible' happened:\n   %s\n", str);
    133    fprintf(stderr,
    134            "Please report this bug at: %s\n\n", VG_BUGS_TO);
    135    exit(1);
    136 }
    137 
    138 __attribute__ ((noreturn))
    139 static void my_assert_fail ( const char* expr, const char* file, int line, const char* fn )
    140 {
    141    fprintf(stderr,
    142            "\nvalgrind-di-server: %s:%d (%s): Assertion '%s' failed.\n",
    143            file, line, fn, expr );
    144    fprintf(stderr,
    145            "Please report this bug at: %s\n\n", VG_BUGS_TO);
    146    exit(1);
    147 }
    148 
    149 #undef assert
    150 
    151 #define assert(expr)                                             \
    152   ((void) ((expr) ? 0 :					         \
    153 	   (my_assert_fail (VG_STRINGIFY(expr),	                 \
    154                             __FILE__, __LINE__,                  \
    155                             __PRETTY_FUNCTION__), 0)))
    156 
    157 
    158 /*---------------------------------------------------------------*/
    159 
    160 /* Allocate some memory. Return iff successful. */
    161 static void *my_malloc(size_t amount)
    162 {
    163   void *p = malloc(amount ?: 1);
    164 
    165   if (p == NULL) {
    166      fprintf(stderr, "Memory allocation failed; cannot continue.\n");
    167      exit(1);
    168   }
    169   return p;
    170 }
    171 
    172 /*---------------------------------------------------------------*/
    173 
    174 /* Holds the state that we need to track, for each connection. */
    175 typedef
    176    struct {
    177       // is this entry in use?
    178       Bool in_use;
    179       // socket descriptor to communicate with client.  Initialised as
    180       // soon as this entry is created.
    181       int  conn_sd;
    182       // fd for the file that we are connected to.  Zero if not
    183       // currently connected to any file.
    184       int   file_fd;
    185       ULong file_size;
    186       // Session ID
    187       ULong session_id;
    188       // How many bytes and chunks sent?
    189       ULong stats_n_rdok_frames;
    190       ULong stats_n_read_unz_bytes; // bytes via READ (uncompressed)
    191       ULong stats_n_read_z_bytes;   // bytes via READ (compressed)
    192    }
    193    ConnState;
    194 
    195 /* The state itself. */
    196 static int       conn_count = 0;
    197 static ConnState *conn_state;
    198 
    199 /* Issues unique session ID values. */
    200 static ULong next_session_id = 1;
    201 
    202 
    203 /*---------------------------------------------------------------*/
    204 
    205 // Code that is duplicated with the client :-(
    206 
    207 /* The following Adler-32 checksum code is taken from zlib-1.2.3, which
    208    has the following copyright notice. */
    209 /*
    210 Copyright notice:
    211 
    212  (C) 1995-2004 Jean-loup Gailly and Mark Adler
    213 
    214   This software is provided 'as-is', without any express or implied
    215   warranty.  In no event will the authors be held liable for any damages
    216   arising from the use of this software.
    217 
    218   Permission is granted to anyone to use this software for any purpose,
    219   including commercial applications, and to alter it and redistribute it
    220   freely, subject to the following restrictions:
    221 
    222   1. The origin of this software must not be misrepresented; you must not
    223      claim that you wrote the original software. If you use this software
    224      in a product, an acknowledgment in the product documentation would be
    225      appreciated but is not required.
    226   2. Altered source versions must be plainly marked as such, and must not be
    227      misrepresented as being the original software.
    228   3. This notice may not be removed or altered from any source distribution.
    229 
    230   Jean-loup Gailly        Mark Adler
    231   jloup (at) gzip.org          madler (at) alumni.caltech.edu
    232 
    233 If you use the zlib library in a product, we would appreciate *not*
    234 receiving lengthy legal documents to sign. The sources are provided
    235 for free but without warranty of any kind.  The library has been
    236 entirely written by Jean-loup Gailly and Mark Adler; it does not
    237 include third-party code.
    238 
    239 If you redistribute modified sources, we would appreciate that you include
    240 in the file ChangeLog history information documenting your changes. Please
    241 read the FAQ for more information on the distribution of modified source
    242 versions.
    243 */
    244 
    245 /* Update a running Adler-32 checksum with the bytes buf[0..len-1] and
    246    return the updated checksum. If buf is NULL, this function returns
    247    the required initial value for the checksum. An Adler-32 checksum is
    248    almost as reliable as a CRC32 but can be computed much faster. */
    249 static
    250 UInt adler32( UInt adler, const UChar* buf, UInt len )
    251 {
    252 #  define BASE 65521UL    /* largest prime smaller than 65536 */
    253 #  define NMAX 5552
    254    /* NMAX is the largest n such that
    255       255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
    256 
    257 #  define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}
    258 #  define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
    259 #  define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
    260 #  define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
    261 #  define DO16(buf)   DO8(buf,0); DO8(buf,8);
    262 
    263    /* The zlib sources recommend this definition of MOD if the
    264       processor cannot do integer division in hardware. */
    265 #  define MOD(a) \
    266       do { \
    267           if (a >= (BASE << 16)) a -= (BASE << 16); \
    268           if (a >= (BASE << 15)) a -= (BASE << 15); \
    269           if (a >= (BASE << 14)) a -= (BASE << 14); \
    270           if (a >= (BASE << 13)) a -= (BASE << 13); \
    271           if (a >= (BASE << 12)) a -= (BASE << 12); \
    272           if (a >= (BASE << 11)) a -= (BASE << 11); \
    273           if (a >= (BASE << 10)) a -= (BASE << 10); \
    274           if (a >= (BASE << 9)) a -= (BASE << 9); \
    275           if (a >= (BASE << 8)) a -= (BASE << 8); \
    276           if (a >= (BASE << 7)) a -= (BASE << 7); \
    277           if (a >= (BASE << 6)) a -= (BASE << 6); \
    278           if (a >= (BASE << 5)) a -= (BASE << 5); \
    279           if (a >= (BASE << 4)) a -= (BASE << 4); \
    280           if (a >= (BASE << 3)) a -= (BASE << 3); \
    281           if (a >= (BASE << 2)) a -= (BASE << 2); \
    282           if (a >= (BASE << 1)) a -= (BASE << 1); \
    283           if (a >= BASE) a -= BASE; \
    284       } while (0)
    285 #  define MOD4(a) \
    286       do { \
    287           if (a >= (BASE << 4)) a -= (BASE << 4); \
    288           if (a >= (BASE << 3)) a -= (BASE << 3); \
    289           if (a >= (BASE << 2)) a -= (BASE << 2); \
    290           if (a >= (BASE << 1)) a -= (BASE << 1); \
    291           if (a >= BASE) a -= BASE; \
    292       } while (0)
    293 
    294     UInt sum2;
    295     UInt n;
    296 
    297     /* split Adler-32 into component sums */
    298     sum2 = (adler >> 16) & 0xffff;
    299     adler &= 0xffff;
    300 
    301     /* in case user likes doing a byte at a time, keep it fast */
    302     if (len == 1) {
    303         adler += buf[0];
    304         if (adler >= BASE)
    305             adler -= BASE;
    306         sum2 += adler;
    307         if (sum2 >= BASE)
    308             sum2 -= BASE;
    309         return adler | (sum2 << 16);
    310     }
    311 
    312     /* initial Adler-32 value (deferred check for len == 1 speed) */
    313     if (buf == NULL)
    314         return 1L;
    315 
    316     /* in case short lengths are provided, keep it somewhat fast */
    317     if (len < 16) {
    318         while (len--) {
    319             adler += *buf++;
    320             sum2 += adler;
    321         }
    322         if (adler >= BASE)
    323             adler -= BASE;
    324         MOD4(sum2);             /* only added so many BASE's */
    325         return adler | (sum2 << 16);
    326     }
    327 
    328     /* do length NMAX blocks -- requires just one modulo operation */
    329     while (len >= NMAX) {
    330         len -= NMAX;
    331         n = NMAX / 16;          /* NMAX is divisible by 16 */
    332         do {
    333             DO16(buf);          /* 16 sums unrolled */
    334             buf += 16;
    335         } while (--n);
    336         MOD(adler);
    337         MOD(sum2);
    338     }
    339 
    340     /* do remaining bytes (less than NMAX, still just one modulo) */
    341     if (len) {                  /* avoid modulos if none remaining */
    342         while (len >= 16) {
    343             len -= 16;
    344             DO16(buf);
    345             buf += 16;
    346         }
    347         while (len--) {
    348             adler += *buf++;
    349             sum2 += adler;
    350         }
    351         MOD(adler);
    352         MOD(sum2);
    353     }
    354 
    355     /* return recombined sums */
    356     return adler | (sum2 << 16);
    357 
    358 #  undef MOD4
    359 #  undef MOD
    360 #  undef DO16
    361 #  undef DO8
    362 #  undef DO4
    363 #  undef DO2
    364 #  undef DO1
    365 #  undef NMAX
    366 #  undef BASE
    367 }
    368 
    369 
    370 /* A frame.  The first 4 bytes of |data| give the kind of the frame,
    371    and the rest of it is kind-specific data. */
    372 typedef  struct { UChar* data; SizeT n_data; }  Frame;
    373 
    374 
    375 static void write_UInt_le ( /*OUT*/UChar* dst, UInt n )
    376 {
    377    Int i;
    378    for (i = 0; i <= 3; i++) {
    379       dst[i] = (UChar)(n & 0xFF);
    380       n >>= 8;
    381    }
    382 }
    383 
    384 static UInt read_UInt_le ( UChar* src )
    385 {
    386    UInt r = 0;
    387    Int i;
    388    for (i = 3; i >= 0; i--) {
    389       r <<= 8;
    390       r += (UInt)src[i];
    391    }
    392    return r;
    393 }
    394 
    395 static void write_ULong_le ( /*OUT*/UChar* dst, ULong n )
    396 {
    397    Int i;
    398    for (i = 0; i <= 7; i++) {
    399       dst[i] = (UChar)(n & 0xFF);
    400       n >>= 8;
    401    }
    402 }
    403 
    404 static ULong read_ULong_le ( UChar* src )
    405 {
    406    ULong r = 0;
    407    Int i;
    408    for (i = 7; i >= 0; i--) {
    409       r <<= 8;
    410       r += (ULong)src[i];
    411    }
    412    return r;
    413 }
    414 
    415 static Frame* mk_Frame_asciiz ( const char* tag, const char* str )
    416 {
    417    assert(strlen(tag) == 4);
    418    Frame* f = calloc(sizeof(Frame), 1);
    419    size_t n_str = strlen(str);
    420    f->n_data = 4 + n_str + 1;
    421    f->data = calloc(f->n_data, 1);
    422    memcpy(&f->data[0], tag, 4);
    423    memcpy(&f->data[4], str, n_str);
    424    assert(f->data[4 + n_str] == 0);
    425    return f;
    426 }
    427 
    428 static Bool parse_Frame_noargs ( Frame* fr, const HChar* tag )
    429 {
    430    assert(strlen(tag) == 4);
    431    if (!fr || !fr->data) return False;
    432    if (fr->n_data < 4) return False;
    433    if (memcmp(&fr->data[0], tag, 4) != 0) return False;
    434    if (fr->n_data != 4) return False;
    435    return True;
    436 }
    437 
    438 static Bool parse_Frame_asciiz ( Frame* fr, const HChar* tag,
    439                                  /*OUT*/UChar** str )
    440 {
    441    assert(strlen(tag) == 4);
    442    if (!fr || !fr->data) return False;
    443    if (fr->n_data < 4) return False;
    444    if (memcmp(&fr->data[0], tag, 4) != 0) return False;
    445    if (fr->n_data < 5) return False; // else there isn't even enough
    446                                      // space for the terminating zero
    447    /* Find the terminating zero and ensure it's right at the end
    448       of the data.  If not, the frame is malformed. */
    449    SizeT i = 4;
    450    while (True) {
    451       if (i >= fr->n_data) break;
    452       if (fr->data[i] == 0) break;
    453       i++;
    454    }
    455    assert(i <= fr->n_data);
    456    if (i == fr->n_data-1 && fr->data[i] == 0) {
    457       *str = &fr->data[4];
    458       return True;
    459    } else {
    460       return False;
    461    }
    462 }
    463 
    464 static Frame* mk_Frame_le64 ( const HChar* tag, ULong n1 )
    465 {
    466    assert(strlen(tag) == 4);
    467    Frame* f = calloc(sizeof(Frame), 1);
    468    f->n_data = 4 + 1*8;
    469    f->data = calloc(f->n_data, 1);
    470    memcpy(&f->data[0], tag, 4);
    471    write_ULong_le(&f->data[4 + 0*8], n1);
    472    return f;
    473 }
    474 
    475 static Frame* mk_Frame_le64_le64 ( const HChar* tag, ULong n1, ULong n2 )
    476 {
    477    assert(strlen(tag) == 4);
    478    Frame* f = calloc(sizeof(Frame), 1);
    479    f->n_data = 4 + 2*8;
    480    f->data = calloc(f->n_data, 1);
    481    memcpy(&f->data[0], tag, 4);
    482    write_ULong_le(&f->data[4 + 0*8], n1);
    483    write_ULong_le(&f->data[4 + 1*8], n2);
    484    return f;
    485 }
    486 
    487 static Bool parse_Frame_le64_le64_le64 ( Frame* fr, const HChar* tag,
    488                                          /*OUT*/ULong* n1, /*OUT*/ULong* n2,
    489                                          /*OUT*/ULong* n3 )
    490 {
    491    assert(strlen(tag) == 4);
    492    if (!fr || !fr->data) return False;
    493    if (fr->n_data < 4) return False;
    494    if (memcmp(&fr->data[0], tag, 4) != 0) return False;
    495    if (fr->n_data != 4 + 3*8) return False;
    496    *n1 = read_ULong_le(&fr->data[4 + 0*8]);
    497    *n2 = read_ULong_le(&fr->data[4 + 1*8]);
    498    *n3 = read_ULong_le(&fr->data[4 + 2*8]);
    499    return True;
    500 }
    501 
    502 static Frame* mk_Frame_le64_le64_le64_bytes (
    503                  const HChar* tag,
    504                  ULong n1, ULong n2, ULong n3, ULong n_data,
    505                  /*OUT*/UChar** data )
    506 {
    507    assert(strlen(tag) == 4);
    508    Frame* f = calloc(sizeof(Frame), 1);
    509    f->n_data = 4 + 3*8 + n_data;
    510    f->data = calloc(f->n_data, 1);
    511    memcpy(&f->data[0], tag, 4);
    512    write_ULong_le(&f->data[4 + 0*8], n1);
    513    write_ULong_le(&f->data[4 + 1*8], n2);
    514    write_ULong_le(&f->data[4 + 2*8], n3);
    515    *data = &f->data[4 + 3*8];
    516    return f;
    517 }
    518 
    519 static void free_Frame ( Frame* fr )
    520 {
    521    assert(fr && fr->data);
    522    free(fr->data);
    523    free(fr);
    524 }
    525 
    526 
    527 static void set_blocking ( int sd )
    528 {
    529    int res;
    530    res = fcntl(sd, F_GETFL);
    531    res = fcntl(sd, F_SETFL, res & ~O_NONBLOCK);
    532    if (res != 0) {
    533       perror("fcntl failed");
    534       panic("set_blocking");
    535    }
    536 }
    537 
    538 
    539 #if 0
    540 static void set_nonblocking ( int sd )
    541 {
    542    int res;
    543    res = fcntl(sd, F_GETFL);
    544    res = fcntl(sd, F_SETFL, res | O_NONBLOCK);
    545    if (res != 0) {
    546       perror("fcntl failed");
    547       panic("set_nonblocking");
    548    }
    549 }
    550 #endif
    551 
    552 
    553 /* Tries to read 'len' bytes from fd, blocking if necessary.  Assumes
    554    fd has been set in blocking mode.  If it returns with the number of
    555    bytes read < len, it means that either fd was closed, or there was
    556    an error on it. */
    557 static SizeT my_read ( Int fd, UChar* buf, SizeT len )
    558 {
    559   //set_blocking(fd);
    560    SizeT nRead = 0;
    561    while (1) {
    562       if (nRead == len) return nRead;
    563       assert(nRead < len);
    564       SizeT nNeeded = len - nRead;
    565       assert(nNeeded > 0);
    566       SSizeT n = read(fd, &buf[nRead], nNeeded);
    567       if (n <= 0) return nRead; /* error or EOF */
    568       nRead += n;
    569    }
    570 }
    571 
    572 /* Tries to write 'len' bytes to fd, blocking if necessary.  Assumes
    573    fd has been set in blocking mode.  If it returns with the number of
    574    bytes written < len, it means that either fd was closed, or there was
    575    an error on it. */
    576 static SizeT my_write ( Int fd, UChar* buf, SizeT len )
    577 {
    578   //set_nonblocking(fd);
    579    SizeT nWritten = 0;
    580    while (1) {
    581       if (nWritten == len) return nWritten;
    582       assert(nWritten < len);
    583       SizeT nStillToDo = len - nWritten;
    584       assert(nStillToDo > 0);
    585       SSizeT n = write(fd, &buf[nWritten], nStillToDo);
    586       if (n < 0) return nWritten; /* error or EOF */
    587       nWritten += n;
    588    }
    589 }
    590 
    591 
    592 static UInt calc_gnu_debuglink_crc32(/*OUT*/Bool* ok, int fd, ULong size)
    593 {
    594   static const UInt crc32_table[256] =
    595     {
    596       0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
    597       0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
    598       0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
    599       0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
    600       0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
    601       0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
    602       0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
    603       0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
    604       0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
    605       0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
    606       0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
    607       0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
    608       0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
    609       0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
    610       0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
    611       0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
    612       0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
    613       0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
    614       0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
    615       0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
    616       0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
    617       0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
    618       0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
    619       0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    620       0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
    621       0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
    622       0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
    623       0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
    624       0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
    625       0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
    626       0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
    627       0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
    628       0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
    629       0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
    630       0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
    631       0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
    632       0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
    633       0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
    634       0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
    635       0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
    636       0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
    637       0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
    638       0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
    639       0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
    640       0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
    641       0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
    642       0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
    643       0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    644       0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
    645       0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
    646       0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
    647       0x2d02ef8d
    648     };
    649 
    650       /* Work through the image in 1 KB chunks. */
    651       UInt  crc      = 0xFFFFFFFF;
    652       ULong img_szB  = size;
    653       ULong curr_off = 0;
    654       while (1) {
    655          assert(curr_off >= 0 && curr_off <= img_szB);
    656          if (curr_off == img_szB) break;
    657          ULong avail = img_szB - curr_off;
    658          assert(avail > 0 && avail <= img_szB);
    659          if (avail > 65536) avail = 65536;
    660          UChar buf[65536];
    661          Int nRead = pread(fd, buf, avail, curr_off);
    662          if (nRead <= 0) { /* EOF or error on the file; neither should happen */
    663             *ok = False;
    664             return 0;
    665          }
    666          /* this is a kludge .. we should loop around pread and deal
    667             with short reads, for whatever reason */
    668          assert(nRead == avail);
    669          UInt i;
    670          for (i = 0; i < (UInt)nRead; i++)
    671             crc = crc32_table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8);
    672          curr_off += nRead;
    673       }
    674       *ok = True;
    675       return ~crc & 0xFFFFFFFF;
    676    }
    677 
    678 
    679 /*---------------------------------------------------------------*/
    680 
    681 /* Handle a transaction for conn_state[conn_no].  There is incoming
    682    data available; read it and send back an appropriate response.
    683    Returns a boolean indicating whether the connection has been
    684    closed; in which case this function does all necessary cleanup and
    685    leaves conn_state[conn_no] in a not-in-use state. */
    686 
    687 static Bool handle_transaction ( int conn_no )
    688 {
    689    Frame* req = NULL; /* the request frame that we receive */
    690    Frame* res = NULL; /* the response frame that we send back */
    691 
    692    assert(conn_no >= 0 && conn_no < M_CONNECTIONS);
    693    assert(conn_state[conn_no].in_use);
    694 
    695    //printf("SERVER: handle_transaction(%d)\n", conn_no); fflush(stdout);
    696 
    697    Int sd = conn_state[conn_no].conn_sd;
    698 
    699    /* Get a frame out of the channel. */
    700    UChar rd_first8[8];  // adler32; length32
    701    { Int r = my_read(sd, &rd_first8[0], 8);
    702      if (r == 0) goto client_closed_conn;
    703      if (r != 8) goto fail;
    704    }
    705    UInt rd_adler = read_UInt_le(&rd_first8[0]);
    706    UInt rd_len   = read_UInt_le(&rd_first8[4]);
    707    /* Allocate a Frame to hold the result data, and read into it. */
    708    // Reject obviously-insane length fields.
    709    if (rd_len > 4*1024*1024) goto fail;
    710    assert(req == NULL);
    711    req = calloc(sizeof(Frame), 1);
    712    req->n_data = rd_len;
    713    req->data = calloc(rd_len, 1);
    714    if (rd_len > 0) {
    715       Int r = my_read(sd, req->data, req->n_data);
    716       if (r != rd_len) goto fail;
    717    }
    718 //printf("SERVER: recv %c%c%c%c\n", req->data[0], req->data[1], req->data[2], req->data[3]); fflush(stdout);
    719 
    720    /* Compute the checksum for the received data, and check it. */
    721    UInt adler = adler32(0, NULL, 0); // initial value
    722    adler = adler32(adler, &rd_first8[4], 4);
    723    if (req->n_data > 0)
    724       adler = adler32(adler, req->data, req->n_data);
    725 
    726    if (adler/*computed*/ != rd_adler/*expected*/) goto fail;
    727 
    728    /* Now we have a request frame.  Cook up a response. */
    729    assert(res == NULL);
    730 
    731    UChar* filename = NULL;
    732    ULong req_session_id = 0, req_offset = 0, req_len = 0;
    733 
    734    if (parse_Frame_noargs(req, "VERS")) {
    735       res = mk_Frame_asciiz("VEOK", "Valgrind Debuginfo Server, Version 1");
    736    }
    737    else
    738    if (parse_Frame_noargs(req, "CRC3")) {
    739       /* FIXME: add a session ID to this request, and check it */
    740       if (conn_state[conn_no].file_fd == 0) {
    741          res = mk_Frame_asciiz("CRC3", "FAIL: not connected to file");
    742       } else {
    743          Bool ok    = False;
    744          UInt crc32 = calc_gnu_debuglink_crc32(&ok,
    745                                                conn_state[conn_no].file_fd,
    746                                                conn_state[conn_no].file_size);
    747          if (ok) {
    748             res = mk_Frame_le64("CROK", (ULong)crc32);
    749          } else {
    750             res = mk_Frame_asciiz("FAIL", "CRC3: I/O error reading file");
    751          }
    752       }
    753    }
    754    else
    755    if (parse_Frame_asciiz(req, "OPEN", &filename)) {
    756       Bool ok = True;
    757       int  fd = 0;
    758       if (conn_state[conn_no].file_fd != 0) {
    759          res = mk_Frame_asciiz("FAIL", "OPEN: already connected to file");
    760          ok = False;
    761       }
    762       if (ok) {
    763          assert(clo_serverpath);
    764          fd = open((char*)filename, O_RDONLY);
    765          if (fd == -1) {
    766             res = mk_Frame_asciiz("FAIL", "OPEN: cannot open file");
    767             printf("(%d) SessionID %llu: open failed for \"%s\"\n",
    768                    conn_count, conn_state[conn_no].session_id, filename );
    769             ok = False;
    770          } else {
    771             assert(fd > 2);
    772          }
    773       }
    774       if (ok) {
    775          struct stat stat_buf;
    776          int r = fstat(fd, &stat_buf);
    777          if (r != 0) {
    778             res = mk_Frame_asciiz("FAIL", "OPEN: cannot stat file");
    779             ok = False;
    780          }
    781          if (ok && stat_buf.st_size == 0) {
    782             res = mk_Frame_asciiz("FAIL", "OPEN: file has zero size");
    783             ok = False;
    784          }
    785          if (ok) {
    786             conn_state[conn_no].file_fd   = fd;
    787             conn_state[conn_no].file_size = stat_buf.st_size;
    788             assert(res == NULL);
    789             res = mk_Frame_le64_le64("OPOK", conn_state[conn_no].session_id,
    790                                              conn_state[conn_no].file_size);
    791             printf("(%d) SessionID %llu: open successful for \"%s\"\n",
    792                    conn_count, conn_state[conn_no].session_id, filename );
    793             fflush(stdout);
    794          }
    795       }
    796    }
    797    else
    798    if (parse_Frame_le64_le64_le64(req, "READ", &req_session_id,
    799                                   &req_offset, &req_len)) {
    800       /* Because each new connection is associated with its own socket
    801          descriptor and hence with a particular conn_no, the requested
    802          session-ID is redundant -- it must be the one associated with
    803          this slot.  But check anyway. */
    804       Bool ok = True;
    805       if (req_session_id != conn_state[conn_no].session_id) {
    806          res = mk_Frame_asciiz("FAIL", "READ: invalid session ID");
    807          ok = False;
    808       }
    809       /* Check we're connected to a file, and if so range-check the
    810          request. */
    811       if (ok && conn_state[conn_no].file_fd == 0) {
    812          res = mk_Frame_asciiz("FAIL", "READ: no associated file");
    813          ok = False;
    814       }
    815       if (ok && (req_len == 0 || req_len > 4*1024*1024)) {
    816          res = mk_Frame_asciiz("FAIL", "READ: invalid request size");
    817          ok = False;
    818       }
    819       if (ok && req_len + req_offset > conn_state[conn_no].file_size) {
    820          res = mk_Frame_asciiz("FAIL", "READ: request exceeds file size");
    821          ok = False;
    822       }
    823       /* Try to read the file. */
    824       if (ok) {
    825          /* First, allocate a temp buf and read from the file into it. */
    826          /* FIXME: what if pread reads short and we have to redo it? */
    827          UChar* unzBuf = my_malloc(req_len);
    828          size_t nRead = pread(conn_state[conn_no].file_fd,
    829                               unzBuf, req_len, req_offset);
    830          if (nRead != req_len) {
    831             free_Frame(res);
    832             res = mk_Frame_asciiz("FAIL", "READ: I/O error reading file");
    833             ok = False;
    834          }
    835          if (ok) {
    836             // Now compress it with LZO.  LZO appears to recommend
    837             // the worst-case output size as (in_len + in_len / 16 + 67).
    838             // Be more conservative here.
    839 #           define STACK_ALLOC(var,size) \
    840                lzo_align_t __LZO_MMODEL \
    841                   var [ ((size) \
    842                         + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ]
    843             STACK_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS);
    844 #           undef STACK_ALLOC
    845             UInt zLenMax = req_len + req_len / 4 + 1024;
    846             UChar* zBuf = my_malloc(zLenMax);
    847             lzo_uint zLen = zLenMax;
    848             Int lzo_rc = lzo1x_1_compress(unzBuf, req_len,
    849                                           zBuf, &zLen, wrkmem);
    850             if (lzo_rc == LZO_E_OK) {
    851               //printf("XXXXX req_len %u  zLen %u\n", (UInt)req_len, (UInt)zLen);
    852                assert(zLen <= zLenMax);
    853                /* Make a frame to put the results in.  Bytes 24 and
    854                   onwards need to be filled from the compressed data,
    855                   and 'buf' is set to point to the right bit. */
    856                UChar* buf = NULL;
    857                res = mk_Frame_le64_le64_le64_bytes
    858                  ("RDOK", req_session_id, req_offset, req_len, zLen, &buf);
    859                assert(res);
    860                assert(buf);
    861                memcpy(buf, zBuf, zLen);
    862                // Update stats
    863                conn_state[conn_no].stats_n_rdok_frames++;
    864                conn_state[conn_no].stats_n_read_unz_bytes += req_len;
    865                conn_state[conn_no].stats_n_read_z_bytes   += zLen;
    866             } else {
    867                ok = False;
    868                free_Frame(res);
    869                res = mk_Frame_asciiz("FAIL", "READ: LZO failed");
    870             }
    871             free(zBuf);
    872          }
    873          free(unzBuf);
    874       }
    875    }
    876    else {
    877       res = mk_Frame_asciiz("FAIL", "Invalid request frame type");
    878    }
    879 
    880    /* All paths through the above should result in an assignment to |res|. */
    881    assert(res != NULL);
    882 
    883    /* And send the response frame back to the client. */
    884    /* What goes on the wire is:
    885          adler(le32) n_data(le32) data[0 .. n_data-1]
    886       where the checksum covers n_data as well as data[].
    887    */
    888    /* The initial Adler-32 value */
    889    adler = adler32(0, NULL, 0);
    890 
    891    /* Fold in the length field, encoded as le32. */
    892    UChar wr_first8[8];
    893    write_UInt_le(&wr_first8[4], res->n_data);
    894    adler = adler32(adler, &wr_first8[4], 4);
    895    /* Fold in the data values */
    896    adler = adler32(adler, res->data, res->n_data);
    897    write_UInt_le(&wr_first8[0], adler);
    898 
    899    Int r = my_write(sd, &wr_first8[0], 8);
    900    if (r != 8) goto fail;
    901    assert(res->n_data >= 4); // else ill formed -- no KIND field
    902    r = my_write(sd, res->data, res->n_data);
    903    if (r != res->n_data) goto fail;
    904 
    905 //printf("SERVER: send %c%c%c%c\n", res->data[0], res->data[1], res->data[2], res->data[3]); fflush(stdout);
    906 
    907    /* So, success. */
    908    free_Frame(req);
    909    free_Frame(res);
    910    return False;  /* "connection still in use" */
    911 
    912    // Is there any difference between these?
    913   client_closed_conn:
    914   fail:
    915    if (conn_state[conn_no].conn_sd > 0)
    916       close(conn_state[conn_no].conn_sd);
    917    if (conn_state[conn_no].file_fd > 0)
    918       close(conn_state[conn_no].file_fd);
    919 
    920    if (conn_state[conn_no].stats_n_rdok_frames > 0) {
    921       printf("(%d) SessionID %llu:   sent %llu frames, "
    922              "%llu MB (unz), %llu MB (z), ratio %4.2f:1\n",
    923              conn_count, conn_state[conn_no].session_id,
    924              conn_state[conn_no].stats_n_rdok_frames,
    925              conn_state[conn_no].stats_n_read_unz_bytes / 1000000,
    926              conn_state[conn_no].stats_n_read_z_bytes / 1000000,
    927              (double)conn_state[conn_no].stats_n_read_unz_bytes
    928                / (double)conn_state[conn_no].stats_n_read_z_bytes);
    929       printf("(%d) SessionID %llu: closed\n",
    930              conn_count, conn_state[conn_no].session_id);
    931 
    932       fflush(stdout);
    933    }
    934 
    935    memset(&conn_state[conn_no], 0, sizeof(conn_state[conn_no]));
    936    if (req) free_Frame(req);
    937    if (res) free_Frame(res);
    938    return True; /* "connection has been closed" */
    939 }
    940 
    941 
    942 /*---------------------------------------------------------------*/
    943 
    944 
    945 
    946 #if 0
    947 static void copyout ( char* buf, int nbuf )
    948 {
    949    int i;
    950    for (i = 0; i < nbuf; i++) {
    951       if (buf[i] == '\n') {
    952          fprintf(stdout, "\n(%d) ", conn_count);
    953       } else {
    954          __attribute__((unused)) size_t ignored
    955             = fwrite(&buf[i], 1, 1, stdout);
    956       }
    957    }
    958    fflush(stdout);
    959 }
    960 
    961 static int read_from_sd ( int sd )
    962 {
    963    char buf[100];
    964    int n;
    965 
    966    set_blocking(sd);
    967    n = read(sd, buf, 99);
    968    if (n <= 0) return 0; /* closed */
    969    copyout(buf, n);
    970 
    971    set_nonblocking(sd);
    972    while (1) {
    973       n = read(sd, buf, 100);
    974       if (n <= 0) return 1; /* not closed */
    975       copyout(buf, n);
    976    }
    977 }
    978 #endif
    979 
    980 static void snooze ( void )
    981 {
    982    struct timespec req;
    983    req.tv_sec = 0;
    984    req.tv_nsec = 200 * 1000 * 1000;
    985    nanosleep(&req,NULL);
    986 }
    987 
    988 
    989 /* returns 0 if negative, or > BOUND or invalid characters were found */
    990 static int atoi_with_bound ( const char* str, int bound )
    991 {
    992    int n = 0;
    993    while (1) {
    994       if (*str == 0)
    995          break;
    996       if (*str < '0' || *str > '9')
    997          return 0;
    998       n = 10*n + (int)(*str - '0');
    999       str++;
   1000       if (n >= bound)
   1001          return 0;
   1002    }
   1003    return n;
   1004 }
   1005 
   1006 
   1007 /* returns 0 if invalid, else port # */
   1008 static int atoi_portno ( const char* str )
   1009 {
   1010    int n = atoi_with_bound(str, 65536);
   1011 
   1012    if (n < 1024)
   1013       return 0;
   1014    return n;
   1015 }
   1016 
   1017 
   1018 static void usage ( void )
   1019 {
   1020    fprintf(stderr,
   1021       "\n"
   1022       "usage is:\n"
   1023       "\n"
   1024       "   valgrind-di-server [--exit-at-zero|-e] [port-number]\n"
   1025       "\n"
   1026       "   where   --exit-at-zero or -e causes the listener to exit\n"
   1027       "           when the number of connections falls back to zero\n"
   1028       "           (the default is to keep listening forever)\n"
   1029       "\n"
   1030       "           --max-connect=INT can be used to increase the maximum\n"
   1031       "           number of connected processes (default = %d).\n"
   1032       "           INT must be positive and less than %d.\n"
   1033       "\n"
   1034       "           port-number is the default port on which to listen for\n"
   1035       "           connections.  It must be between 1024 and 65535.\n"
   1036       "           Current default is %d.\n"
   1037       "\n"
   1038       ,
   1039       M_CONNECTIONS_DEFAULT, M_CONNECTIONS_MAX, VG_CLO_DEFAULT_LOGPORT
   1040    );
   1041    exit(1);
   1042 }
   1043 
   1044 
   1045 static void banner ( const char* str )
   1046 {
   1047    time_t t;
   1048    t = time(NULL);
   1049    printf("valgrind-di-server %s at %s", str, ctime(&t));
   1050    fflush(stdout);
   1051 }
   1052 
   1053 
   1054 static void exit_routine ( void )
   1055 {
   1056    banner("exited");
   1057    exit(0);
   1058 }
   1059 
   1060 
   1061 static void sigint_handler ( int signo )
   1062 {
   1063    exit_routine();
   1064 }
   1065 
   1066 
   1067 int main (int argc, char** argv)
   1068 {
   1069    int    i, j, res, one;
   1070    int    main_sd, new_sd;
   1071    socklen_t client_len;
   1072    struct sockaddr_in client_addr, server_addr;
   1073 
   1074    char /*bool*/ exit_when_zero = 0;
   1075    int           port = VG_CLO_DEFAULT_LOGPORT;
   1076 
   1077    for (i = 1; i < argc; i++) {
   1078       if (0==strcmp(argv[i], "--exit-at-zero")
   1079           || 0==strcmp(argv[i], "-e")) {
   1080          exit_when_zero = 1;
   1081       }
   1082       else if (0 == strncmp(argv[i], "--max-connect=", 14)) {
   1083          M_CONNECTIONS = atoi_with_bound(strchr(argv[i], '=') + 1, 5000);
   1084          if (M_CONNECTIONS <= 0 || M_CONNECTIONS > M_CONNECTIONS_MAX)
   1085             usage();
   1086       }
   1087       else
   1088       if (atoi_portno(argv[i]) > 0) {
   1089          port = atoi_portno(argv[i]);
   1090       }
   1091       else
   1092       usage();
   1093    }
   1094 
   1095    if (M_CONNECTIONS == 0)   // nothing specified on command line
   1096       M_CONNECTIONS = M_CONNECTIONS_DEFAULT;
   1097 
   1098    conn_state = my_malloc(M_CONNECTIONS * sizeof conn_state[0]);
   1099 
   1100    banner("started");
   1101    signal(SIGINT, sigint_handler);
   1102 
   1103    conn_count = 0;
   1104    memset(conn_state, 0, M_CONNECTIONS * sizeof conn_state[0]);
   1105 
   1106    /* create socket */
   1107    main_sd = socket(AF_INET, SOCK_STREAM, 0);
   1108    if (main_sd < 0) {
   1109       perror("cannot open socket ");
   1110       panic("main -- create socket");
   1111    }
   1112 
   1113    /* allow address reuse to avoid "address already in use" errors */
   1114 
   1115    one = 1;
   1116    if (setsockopt(main_sd, SOL_SOCKET, SO_REUSEADDR,
   1117 		  &one, sizeof(one)) < 0) {
   1118       perror("cannot enable address reuse ");
   1119       panic("main -- enable address reuse");
   1120    }
   1121 
   1122    /* bind server port */
   1123    server_addr.sin_family      = AF_INET;
   1124    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
   1125    server_addr.sin_port        = htons(port);
   1126 
   1127    if (bind(main_sd, (struct sockaddr *) &server_addr,
   1128                      sizeof(server_addr) ) < 0) {
   1129       perror("cannot bind port ");
   1130       panic("main -- bind port");
   1131    }
   1132 
   1133    res = listen(main_sd, M_CONNECTIONS);
   1134    if (res != 0) {
   1135       perror("listen failed ");
   1136       panic("main -- listen");
   1137    }
   1138 
   1139    Bool do_snooze = False;
   1140    while (1) {
   1141 
   1142       if (0 && do_snooze)
   1143          snooze();
   1144 
   1145       /* Snooze after this iteration, unless something happened. */
   1146       do_snooze = True;
   1147 
   1148       /* enquire, using poll, whether there is any activity available on
   1149          the main socket descriptor.  If so, someone is trying to
   1150          connect; get the fd and add it to our table thereof. */
   1151       { struct pollfd ufd;
   1152         while (1) {
   1153            ufd.fd      = main_sd;
   1154            ufd.events  = POLLIN;
   1155            ufd.revents = 0;
   1156            res = poll(&ufd, 1, 0/*ms*/ /* 0=return immediately. */);
   1157            if (res == 0) break;
   1158 
   1159            /* ok, we have someone waiting to connect.  Get the sd. */
   1160            client_len = sizeof(client_addr);
   1161            new_sd = accept(main_sd, (struct sockaddr *)&client_addr,
   1162                                                        &client_len);
   1163            if (new_sd < 0) {
   1164               perror("cannot accept connection ");
   1165               panic("main -- accept connection");
   1166            }
   1167 
   1168            /* find a place to put it. */
   1169 	   assert(new_sd > 0);
   1170            for (i = 0; i < M_CONNECTIONS; i++)
   1171               if (!conn_state[i].in_use)
   1172                  break;
   1173 
   1174            if (i >= M_CONNECTIONS) {
   1175               fprintf(stderr, "\n\nMore than %d concurrent connections.\n"
   1176                       "Restart the server giving --max-connect=INT on the\n"
   1177                       "commandline to increase the limit.\n\n",
   1178                       M_CONNECTIONS);
   1179               exit(1);
   1180            }
   1181 
   1182 assert(one == 1);
   1183 int ret = setsockopt( new_sd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
   1184 assert(ret != -1);
   1185 
   1186            memset(&conn_state[i], 0, sizeof(conn_state[i]));
   1187            conn_state[i].in_use     = True;
   1188            conn_state[i].conn_sd    = new_sd;
   1189            conn_state[i].file_fd    = 0; /* not known yet */
   1190            conn_state[i].session_id = next_session_id++;
   1191            set_blocking(new_sd);
   1192            conn_count++;
   1193            do_snooze = False;
   1194         } /* while (1) */
   1195       }
   1196 
   1197       /* We've processed all new connect requests.  Listen for changes
   1198          to the current set of fds.  This requires gathering up all
   1199          the known conn_sd values and doing poll() on them. */
   1200       static struct pollfd *tmp_pollfd;
   1201       if (tmp_pollfd == NULL)
   1202          tmp_pollfd = my_malloc(M_CONNECTIONS * sizeof tmp_pollfd[0]);
   1203 
   1204       /* And a parallel array which maps entries in tmp_pollfd back to
   1205          entries in conn_state. */
   1206       static int *tmp_pollfd_to_conn_state;
   1207       if (tmp_pollfd_to_conn_state == NULL)
   1208          tmp_pollfd_to_conn_state =
   1209             my_malloc(M_CONNECTIONS * sizeof tmp_pollfd_to_conn_state[0]);
   1210 
   1211       j = 0;
   1212       for (i = 0; i < M_CONNECTIONS; i++) {
   1213          if (!conn_state[i].in_use)
   1214             continue;
   1215          assert(conn_state[i].conn_sd > 2);
   1216          tmp_pollfd[j].fd      = conn_state[i].conn_sd;
   1217          tmp_pollfd[j].events  = POLLIN /* | POLLHUP | POLLNVAL */;
   1218          tmp_pollfd[j].revents = 0;
   1219          tmp_pollfd_to_conn_state[j] = i;
   1220          j++;
   1221       }
   1222 
   1223       res = poll(tmp_pollfd, j, 20/*ms*/ /* 0=return immediately. */ );
   1224       if (res < 0) {
   1225          perror("poll(main) failed");
   1226          panic("poll(main) failed");
   1227       }
   1228 
   1229       /* nothing happened. go round again. */
   1230       if (res == 0) {
   1231          continue;
   1232       }
   1233 
   1234       /* inspect the fds. */
   1235       for (i = 0; i < j; i++) {
   1236 
   1237          if (tmp_pollfd[i].revents & POLLIN) {
   1238             /* We have some activity on tmp_pollfd[i].  We need to
   1239                figure out which conn_state[] entry that corresponds
   1240                to, which is what tmp_pollfd_to_conn_state is for. */
   1241             Int  conn_no  = tmp_pollfd_to_conn_state[i];
   1242             Bool finished = handle_transaction(conn_no);
   1243             if (finished) {
   1244                /* this connection has been closed or otherwise gone
   1245                   bad; forget about it. */
   1246                conn_count--;
   1247                fflush(stdout);
   1248                if (conn_count == 0 && exit_when_zero) {
   1249                   if (0) printf("\n");
   1250                   fflush(stdout);
   1251                   exit_routine();
   1252 	       }
   1253             } else {
   1254                // maybe show stats
   1255                if (conn_state[i].stats_n_rdok_frames > 0
   1256                    && (conn_state[i].stats_n_rdok_frames % 1000) == 0) {
   1257                   printf("(%d) SessionID %llu:   sent %llu frames, "
   1258                          "%llu MB (unz), %llu MB (z)\n",
   1259                          conn_count, conn_state[conn_no].session_id,
   1260                          conn_state[conn_no].stats_n_rdok_frames,
   1261                          conn_state[conn_no].stats_n_read_unz_bytes / 1000000,
   1262                          conn_state[conn_no].stats_n_read_z_bytes / 1000000);
   1263                   fflush(stdout);
   1264                }
   1265             }
   1266          }
   1267 
   1268       } /* for (i = 0; i < j; i++) */
   1269 
   1270       do_snooze = False;
   1271 
   1272    } /* while (1) */
   1273 
   1274    /* NOTREACHED */
   1275 }
   1276 
   1277 ////////////////////////////////////////////////////
   1278 #include "../coregrind/m_debuginfo/minilzo-inl.c"
   1279 
   1280 /*--------------------------------------------------------------------*/
   1281 /*--- end                                     valgrind-di-server.c ---*/
   1282 /*--------------------------------------------------------------------*/
   1283