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 }