📄 nblayer.c
字号:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape Portable Runtime (NSPR). * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#include "prio.h"#include "prmem.h"#include "prprf.h"#include "prlog.h"#include "prerror.h"#include "prnetdb.h"#include "prthread.h"#include "plerror.h"#include "plgetopt.h"#include "prwin16.h"#include <stdlib.h>#include <string.h>/*** Testing layering of I/O**** The layered server** A thread that acts as a server. It creates a TCP listener with a dummy** layer pushed on top. Then listens for incoming connections. Each connection** request for connection will be layered as well, accept one request, echo** it back and close.**** The layered client** Pretty much what you'd expect.*/static PRFileDesc *logFile;static PRDescIdentity identity;static PRNetAddr server_address;static PRIOMethods myMethods;typedef enum {rcv_get_debit, rcv_send_credit, rcv_data} RcvState;typedef enum {xmt_send_debit, xmt_recv_credit, xmt_data} XmtState;struct PRFilePrivate{ RcvState rcvstate; XmtState xmtstate; PRInt32 rcvreq, rcvinprogress; PRInt32 xmtreq, xmtinprogress;};typedef enum Verbosity {silent, quiet, chatty, noisy} Verbosity;static PRIntn minor_iterations = 5;static PRIntn major_iterations = 1;static Verbosity verbosity = quiet;static PRUint16 default_port = 12273;static PRFileDesc *PushLayer(PRFileDesc *stack){ PRStatus rv; PRFileDesc *layer = PR_CreateIOLayerStub(identity, &myMethods); layer->secret = PR_NEWZAP(PRFilePrivate); rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer); PR_ASSERT(PR_SUCCESS == rv); if (verbosity > quiet) PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer, stack); return stack;} /* PushLayer */static PRFileDesc *PopLayer(PRFileDesc *stack){ PRFileDesc *popped = PR_PopIOLayer(stack, identity); if (verbosity > quiet) PR_fprintf(logFile, "Popped layer(0x%x) from stack(0x%x)\n", popped, stack); PR_DELETE(popped->secret); popped->dtor(popped); return stack;} /* PopLayer */static void PR_CALLBACK Client(void *arg){ PRStatus rv; PRIntn mits; PRInt32 ready; PRUint8 buffer[100]; PRPollDesc polldesc; PRIntn empty_flags = 0; PRIntn bytes_read, bytes_sent; PRFileDesc *stack = (PRFileDesc*)arg; /* Initialize the buffer so that Purify won't complain */ memset(buffer, 0, sizeof(buffer)); rv = PR_Connect(stack, &server_address, PR_INTERVAL_NO_TIMEOUT); if ((PR_FAILURE == rv) && (PR_IN_PROGRESS_ERROR == PR_GetError())) { if (verbosity > quiet) PR_fprintf(logFile, "Client connect 'in progress'\n"); do { polldesc.fd = stack; polldesc.out_flags = 0; polldesc.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT; ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT); if ((1 != ready) /* if not 1, then we're dead */ || (0 == (polldesc.in_flags & polldesc.out_flags))) { PR_ASSERT(!"Whoa!"); break; } if (verbosity > quiet) PR_fprintf( logFile, "Client connect 'in progress' [0x%x]\n", polldesc.out_flags); rv = PR_GetConnectStatus(&polldesc); if ((PR_FAILURE == rv) && (PR_IN_PROGRESS_ERROR != PR_GetError())) break; } while (PR_FAILURE == rv); } PR_ASSERT(PR_SUCCESS == rv); if (verbosity > chatty) PR_fprintf(logFile, "Client created connection\n"); for (mits = 0; mits < minor_iterations; ++mits) { bytes_sent = 0; if (verbosity > quiet) PR_fprintf(logFile, "Client sending %d bytes\n", sizeof(buffer)); do { if (verbosity > chatty) PR_fprintf( logFile, "Client sending %d bytes\n", sizeof(buffer) - bytes_sent); ready = PR_Send( stack, buffer + bytes_sent, sizeof(buffer) - bytes_sent, empty_flags, PR_INTERVAL_NO_TIMEOUT); if (verbosity > chatty) PR_fprintf(logFile, "Client send status [%d]\n", ready); if (0 < ready) bytes_sent += ready; else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) { polldesc.fd = stack; polldesc.out_flags = 0; polldesc.in_flags = PR_POLL_WRITE; ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT); if ((1 != ready) /* if not 1, then we're dead */ || (0 == (polldesc.in_flags & polldesc.out_flags))) { PR_ASSERT(!"Whoa!"); break; } } else break; } while (bytes_sent < sizeof(buffer)); PR_ASSERT(sizeof(buffer) == bytes_sent); bytes_read = 0; do { if (verbosity > chatty) PR_fprintf( logFile, "Client receiving %d bytes\n", bytes_sent - bytes_read); ready = PR_Recv( stack, buffer + bytes_read, bytes_sent - bytes_read, empty_flags, PR_INTERVAL_NO_TIMEOUT); if (verbosity > chatty) PR_fprintf( logFile, "Client receive status [%d]\n", ready); if (0 < ready) bytes_read += ready; else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) { polldesc.fd = stack; polldesc.out_flags = 0; polldesc.in_flags = PR_POLL_READ; ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT); if ((1 != ready) /* if not 1, then we're dead */ || (0 == (polldesc.in_flags & polldesc.out_flags))) { PR_ASSERT(!"Whoa!"); break; } } else break; } while (bytes_read < bytes_sent); if (verbosity > chatty) PR_fprintf(logFile, "Client received %d bytes\n", bytes_read); PR_ASSERT(bytes_read == bytes_sent); } if (verbosity > quiet) PR_fprintf(logFile, "Client shutting down stack\n"); rv = PR_Shutdown(stack, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv);} /* Client */static void PR_CALLBACK Server(void *arg){ PRStatus rv; PRInt32 ready; PRUint8 buffer[100]; PRFileDesc *service; PRUintn empty_flags = 0; struct PRPollDesc polldesc; PRIntn bytes_read, bytes_sent; PRFileDesc *stack = (PRFileDesc*)arg; PRNetAddr client_address; do { if (verbosity > chatty) PR_fprintf(logFile, "Server accepting connection\n"); service = PR_Accept(stack, &client_address, PR_INTERVAL_NO_TIMEOUT); if (verbosity > chatty) PR_fprintf(logFile, "Server accept status [0x%p]\n", service); if ((NULL == service) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) { polldesc.fd = stack; polldesc.out_flags = 0; polldesc.in_flags = PR_POLL_READ | PR_POLL_EXCEPT; ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT); if ((1 != ready) /* if not 1, then we're dead */ || (0 == (polldesc.in_flags & polldesc.out_flags))) { PR_ASSERT(!"Whoa!"); break; } } } while (NULL == service); PR_ASSERT(NULL != service); if (verbosity > quiet) PR_fprintf(logFile, "Server accepting connection\n"); do { bytes_read = 0; do { if (verbosity > chatty) PR_fprintf( logFile, "Server receiving %d bytes\n", sizeof(buffer) - bytes_read); ready = PR_Recv( service, buffer + bytes_read, sizeof(buffer) - bytes_read, empty_flags, PR_INTERVAL_NO_TIMEOUT); if (verbosity > chatty) PR_fprintf(logFile, "Server receive status [%d]\n", ready); if (0 < ready) bytes_read += ready; else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) { polldesc.fd = service; polldesc.out_flags = 0; polldesc.in_flags = PR_POLL_READ; ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT); if ((1 != ready) /* if not 1, then we're dead */ || (0 == (polldesc.in_flags & polldesc.out_flags))) { PR_ASSERT(!"Whoa!"); break; } } else break; } while (bytes_read < sizeof(buffer)); if (0 != bytes_read) { if (verbosity > chatty) PR_fprintf(logFile, "Server received %d bytes\n", bytes_read); PR_ASSERT(bytes_read > 0); bytes_sent = 0; do { ready = PR_Send( service, buffer + bytes_sent, bytes_read - bytes_sent, empty_flags, PR_INTERVAL_NO_TIMEOUT); if (0 < ready) { bytes_sent += ready; } else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) { polldesc.fd = service; polldesc.out_flags = 0; polldesc.in_flags = PR_POLL_WRITE; ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT); if ((1 != ready) /* if not 1, then we're dead */ || (0 == (polldesc.in_flags & polldesc.out_flags))) { PR_ASSERT(!"Whoa!"); break; } } else break; } while (bytes_sent < bytes_read); PR_ASSERT(bytes_read == bytes_sent); if (verbosity > chatty) PR_fprintf(logFile, "Server sent %d bytes\n", bytes_sent); } } while (0 != bytes_read); if (verbosity > quiet) PR_fprintf(logFile, "Server shutting down stack\n"); rv = PR_Shutdown(service, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv);} /* Server */static PRStatus PR_CALLBACK MyClose(PRFileDesc *fd){ PR_DELETE(fd->secret); /* manage my secret file object */ return (PR_GetDefaultIOMethods())->close(fd); /* let him do all the work */} /* MyClose */static PRInt16 PR_CALLBACK MyPoll( PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags){ PRInt16 my_flags, new_flags; PRFilePrivate *mine = (PRFilePrivate*)fd->secret; if (0 != (PR_POLL_READ & in_flags)) { /* client thinks he's reading */ switch (mine->rcvstate) { case rcv_send_credit: my_flags = (in_flags & ~PR_POLL_READ) | PR_POLL_WRITE; break; case rcv_data: case rcv_get_debit: my_flags = in_flags; default: break; } } else if (0 != (PR_POLL_WRITE & in_flags)) { /* client thinks he's writing */ switch (mine->xmtstate) { case xmt_recv_credit: my_flags = (in_flags & ~PR_POLL_WRITE) | PR_POLL_READ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -