tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

sendzlf.c (6209B)


      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 /*
      7 * Test: sendzlf.c
      8 *
      9 * Description: send a zero-length file with PR_SendFile and
     10 * PR_TransmitFile.
     11 */
     12 
     13 #define ZERO_LEN_FILE_NAME "zerolen.tmp"
     14 #define HEADER_STR "Header"
     15 #define HEADER_LEN 6 /* length of HEADER_STR, not counting the null byte */
     16 #define TRAILER_STR "Trailer"
     17 #define TRAILER_LEN 7 /* length of TRAILER_STR, not counting the null byte */
     18 
     19 #include "nspr.h"
     20 
     21 #include <stdio.h>
     22 #include <stdlib.h>
     23 #include <string.h>
     24 
     25 static void ClientThread(void* arg) {
     26  PRFileDesc* sock;
     27  PRNetAddr addr;
     28  PRUint16 port = (PRUint16)arg;
     29  char buf[1024];
     30  char* bufPtr;
     31  PRInt32 nbytes;
     32  PRInt32 ntotal;
     33  PRInt32 nexpected;
     34 
     35  sock = PR_NewTCPSocket();
     36  if (NULL == sock) {
     37    fprintf(stderr, "PR_NewTCPSocket failed\n");
     38    exit(1);
     39  }
     40  if (PR_InitializeNetAddr(PR_IpAddrLoopback, port, &addr) == PR_FAILURE) {
     41    fprintf(stderr, "PR_InitializeNetAddr failed\n");
     42    exit(1);
     43  }
     44  if (PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
     45    fprintf(stderr, "PR_Connect failed\n");
     46    exit(1);
     47  }
     48  ntotal = 0;
     49  bufPtr = buf;
     50  while ((nbytes = PR_Read(sock, bufPtr, sizeof(buf) - ntotal)) > 0) {
     51    ntotal += nbytes;
     52    bufPtr += nbytes;
     53  }
     54  if (-1 == nbytes) {
     55    fprintf(stderr, "PR_Read failed\n");
     56    exit(1);
     57  }
     58  nexpected = HEADER_LEN + TRAILER_LEN + TRAILER_LEN + HEADER_LEN + HEADER_LEN;
     59  if (ntotal != nexpected) {
     60    fprintf(stderr, "total bytes read should be %d but is %d\n", nexpected,
     61            ntotal);
     62    exit(1);
     63  }
     64  if (memcmp(buf, HEADER_STR TRAILER_STR TRAILER_STR HEADER_STR HEADER_STR,
     65             nexpected) != 0) {
     66    fprintf(stderr, "wrong data is received\n");
     67    exit(1);
     68  }
     69  if (PR_Close(sock) == PR_FAILURE) {
     70    fprintf(stderr, "PR_Close failed\n");
     71    exit(1);
     72  }
     73 }
     74 
     75 static void ServerThread(void* arg) {
     76  PRFileDesc* listenSock = (PRFileDesc*)arg;
     77  PRFileDesc* acceptSock;
     78  PRFileDesc* file;
     79  PRSendFileData sfd;
     80  char header[1024], trailer[1024];
     81  PRInt32 nbytes;
     82 
     83  /* Create a zero-length file */
     84  file =
     85      PR_Open(ZERO_LEN_FILE_NAME, PR_CREATE_FILE | PR_TRUNCATE | PR_RDWR, 0666);
     86  if (NULL == file) {
     87    fprintf(stderr, "PR_Open failed\n");
     88    exit(1);
     89  }
     90  sfd.fd = file;
     91  sfd.file_offset = 0;
     92  sfd.file_nbytes = 0;
     93  memcpy(header, HEADER_STR, HEADER_LEN);
     94  memcpy(trailer, TRAILER_STR, TRAILER_LEN);
     95  sfd.header = header;
     96  sfd.hlen = HEADER_LEN;
     97  sfd.trailer = trailer;
     98  sfd.tlen = TRAILER_LEN;
     99  acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT);
    100  if (NULL == acceptSock) {
    101    fprintf(stderr, "PR_Accept failed\n");
    102    exit(1);
    103  }
    104  /* Send both header and trailer */
    105  nbytes = PR_SendFile(acceptSock, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
    106                       PR_INTERVAL_NO_TIMEOUT);
    107  if (HEADER_LEN + TRAILER_LEN != nbytes) {
    108    fprintf(stderr, "PR_SendFile should return %d but returned %d\n",
    109            HEADER_LEN + TRAILER_LEN, nbytes);
    110    exit(1);
    111  }
    112  /* Trailer only, no header */
    113  sfd.hlen = 0;
    114  nbytes = PR_SendFile(acceptSock, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
    115                       PR_INTERVAL_NO_TIMEOUT);
    116  if (TRAILER_LEN != nbytes) {
    117    fprintf(stderr, "PR_SendFile should return %d but returned %d\n",
    118            TRAILER_LEN, nbytes);
    119    exit(1);
    120  }
    121  /* Header only, no trailer */
    122  sfd.hlen = HEADER_LEN;
    123  sfd.tlen = 0;
    124  nbytes = PR_SendFile(acceptSock, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
    125                       PR_INTERVAL_NO_TIMEOUT);
    126  if (HEADER_LEN != nbytes) {
    127    fprintf(stderr, "PR_SendFile should return %d but returned %d\n",
    128            HEADER_LEN, nbytes);
    129    exit(1);
    130  }
    131  /* Try PR_TransmitFile */
    132  nbytes = PR_TransmitFile(acceptSock, file, header, HEADER_LEN,
    133                           PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT);
    134  if (HEADER_LEN != nbytes) {
    135    fprintf(stderr, "PR_TransmitFile should return %d but returned %d\n",
    136            HEADER_LEN, nbytes);
    137    exit(1);
    138  }
    139  if (PR_Close(acceptSock) == PR_FAILURE) {
    140    fprintf(stderr, "PR_Close failed\n");
    141    exit(1);
    142  }
    143  if (PR_Close(file) == PR_FAILURE) {
    144    fprintf(stderr, "PR_Close failed\n");
    145    exit(1);
    146  }
    147  if (PR_Delete(ZERO_LEN_FILE_NAME) == PR_FAILURE) {
    148    fprintf(stderr, "PR_Delete failed\n");
    149    exit(1);
    150  }
    151 }
    152 
    153 int main(int argc, char** argv) {
    154  PRFileDesc* listenSock;
    155  PRThread* clientThread;
    156  PRThread* serverThread;
    157  PRNetAddr addr;
    158  PRThreadScope scope = PR_GLOBAL_THREAD;
    159 
    160  listenSock = PR_NewTCPSocket();
    161  if (NULL == listenSock) {
    162    fprintf(stderr, "PR_NewTCPSocket failed\n");
    163    exit(1);
    164  }
    165  if (PR_InitializeNetAddr(PR_IpAddrAny, 0, &addr) == PR_FAILURE) {
    166    fprintf(stderr, "PR_InitializeNetAddr failed\n");
    167    exit(1);
    168  }
    169  if (PR_Bind(listenSock, &addr) == PR_FAILURE) {
    170    fprintf(stderr, "PR_Bind failed\n");
    171    exit(1);
    172  }
    173  /* Find out what port number we are bound to. */
    174  if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) {
    175    fprintf(stderr, "PR_GetSockName failed\n");
    176    exit(1);
    177  }
    178  if (PR_Listen(listenSock, 5) == PR_FAILURE) {
    179    fprintf(stderr, "PR_Listen failed\n");
    180    exit(1);
    181  }
    182 
    183  clientThread = PR_CreateThread(
    184      PR_USER_THREAD, ClientThread, (void*)PR_ntohs(PR_NetAddrInetPort(&addr)),
    185      PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0);
    186  if (NULL == clientThread) {
    187    fprintf(stderr, "PR_CreateThread failed\n");
    188    exit(1);
    189  }
    190  serverThread =
    191      PR_CreateThread(PR_USER_THREAD, ServerThread, listenSock,
    192                      PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0);
    193  if (NULL == serverThread) {
    194    fprintf(stderr, "PR_CreateThread failed\n");
    195    exit(1);
    196  }
    197  if (PR_JoinThread(clientThread) == PR_FAILURE) {
    198    fprintf(stderr, "PR_JoinThread failed\n");
    199    exit(1);
    200  }
    201  if (PR_JoinThread(serverThread) == PR_FAILURE) {
    202    fprintf(stderr, "PR_JoinThread failed\n");
    203    exit(1);
    204  }
    205  if (PR_Close(listenSock) == PR_FAILURE) {
    206    fprintf(stderr, "PR_Close failed\n");
    207    exit(1);
    208  }
    209  printf("PASS\n");
    210  return 0;
    211 }