⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 macsockotpt.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* -*- 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. *//* This turns on UNIX style errors in OT 1.1 headers */#define OTUNIXERRORS 1#include <string.h>#include <Gestalt.h>#include <Files.h>#include <OpenTransport.h>#include <OSUtils.h>#define GESTALT_OPEN_TPT_PRESENT        gestaltOpenTptPresentMask#define GESTALT_OPEN_TPT_TCP_PRESENT    gestaltOpenTptTCPPresentMask#include <OpenTptInternet.h>    // All the internet typedefs#if (UNIVERSAL_INTERFACES_VERSION >= 0x0330)// for some reason Apple removed this typedef.typedef struct OTConfiguration	OTConfiguration;#endif#include "primpl.h"typedef enum SndRcvOpCode {    kSTREAM_SEND,    kSTREAM_RECEIVE,    kDGRAM_SEND,    kDGRAM_RECEIVE} SndRcvOpCode;static struct {	PRLock *    lock;	InetSvcRef  serviceRef;	PRThread *  thread;	void *      cookie;} dnsContext;static pascal void  DNSNotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie);static pascal void  NotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie);static pascal void  RawEndpointNotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie);static PRBool GetState(PRFileDesc *fd, PRBool *readReady, PRBool *writeReady, PRBool *exceptReady);voidWakeUpNotifiedThread(PRThread *thread, OTResult result);extern void WaitOnThisThread(PRThread *thread, PRIntervalTime timeout);extern void DoneWaitingOnThisThread(PRThread *thread);#if TARGET_CARBONOTClientContextPtr  clientContext = NULL;#define INIT_OPEN_TRANSPORT()	InitOpenTransportInContext(kInitOTForExtensionMask, &clientContext)#define OT_OPEN_INTERNET_SERVICES(config, flags, err)	OTOpenInternetServicesInContext(config, flags, err, clientContext)#define OT_OPEN_ENDPOINT(config, flags, info, err)		OTOpenEndpointInContext(config, flags, info, err, clientContext)#else#define INIT_OPEN_TRANSPORT()	InitOpenTransport()#define OT_OPEN_INTERNET_SERVICES(config, flags, err)	OTOpenInternetServices(config, flags, err)#define OT_OPEN_ENDPOINT(config, flags, info, err)		OTOpenEndpoint(config, flags, info, err)#endif /* TARGET_CARBON */static OTNotifyUPP	DNSNotifierRoutineUPP;static OTNotifyUPP NotifierRoutineUPP;static OTNotifyUPP RawEndpointNotifierRoutineUPP;void _MD_InitNetAccess(){    OSErr       err;    OSStatus    errOT;    PRBool      hasOTTCPIP = PR_FALSE;    PRBool      hasOT = PR_FALSE;    long        gestaltResult;    err = Gestalt(gestaltOpenTpt, &gestaltResult);    if (err == noErr)        if (gestaltResult & GESTALT_OPEN_TPT_PRESENT)            hasOT = PR_TRUE;        if (hasOT)        if (gestaltResult & GESTALT_OPEN_TPT_TCP_PRESENT)            hasOTTCPIP = PR_TRUE;            PR_ASSERT(hasOTTCPIP == PR_TRUE);    DNSNotifierRoutineUPP	=  NewOTNotifyUPP(DNSNotifierRoutine);    NotifierRoutineUPP		=  NewOTNotifyUPP(NotifierRoutine);    RawEndpointNotifierRoutineUPP = NewOTNotifyUPP(RawEndpointNotifierRoutine);    errOT = INIT_OPEN_TRANSPORT();    PR_ASSERT(err == kOTNoError);	dnsContext.serviceRef = NULL;	dnsContext.lock = PR_NewLock();	PR_ASSERT(dnsContext.lock != NULL);	dnsContext.thread = _PR_MD_CURRENT_THREAD();	dnsContext.cookie = NULL;	/* XXX Does not handle absence of open tpt and tcp yet! */}static void _MD_FinishInitNetAccess(){    OSStatus    errOT;	if (dnsContext.serviceRef)		return;		    dnsContext.serviceRef = OT_OPEN_INTERNET_SERVICES(kDefaultInternetServicesPath, NULL, &errOT);    if (errOT != kOTNoError) {        dnsContext.serviceRef = NULL;        return;    /* no network -- oh well */    }        PR_ASSERT((dnsContext.serviceRef != NULL) && (errOT == kOTNoError));    /* Install notify function for DNR Address To String completion */    errOT = OTInstallNotifier(dnsContext.serviceRef, DNSNotifierRoutineUPP, &dnsContext);    PR_ASSERT(errOT == kOTNoError);    /* Put us into async mode */    errOT = OTSetAsynchronous(dnsContext.serviceRef);    PR_ASSERT(errOT == kOTNoError);}static pascal void  DNSNotifierRoutine(void * contextPtr, OTEventCode otEvent, OTResult result, void * cookie){#pragma unused(contextPtr)    _PRCPU *    cpu    = _PR_MD_CURRENT_CPU(); 	OSStatus    errOT;		dnsContext.thread->md.osErrCode = result;		dnsContext.cookie = cookie;		switch (otEvent) {		case T_DNRSTRINGTOADDRCOMPLETE:				if (_PR_MD_GET_INTSOFF()) {					dnsContext.thread->md.missedIONotify = PR_TRUE;					cpu->u.missed[cpu->where] |= _PR_MISSED_IO;				} else {					DoneWaitingOnThisThread(dnsContext.thread);				}				break;		        case kOTProviderWillClose:                errOT = OTSetSynchronous(dnsContext.serviceRef);                // fall through to kOTProviderIsClosed case		        case kOTProviderIsClosed:                errOT = OTCloseProvider((ProviderRef)dnsContext.serviceRef);                dnsContext.serviceRef = nil;				if (_PR_MD_GET_INTSOFF()) {					dnsContext.thread->md.missedIONotify = PR_TRUE;					cpu->u.missed[cpu->where] |= _PR_MISSED_IO;				} else {					DoneWaitingOnThisThread(dnsContext.thread);				}                break;        default: // or else we don't handle the event	            PR_ASSERT(otEvent==NULL);			}	// or else we don't handle the event		SignalIdleSemaphore();}static void macsock_map_error(OSStatus err){    _PR_MD_CURRENT_THREAD()->md.osErrCode = err;    if (IsEError(err) || (err >= EPERM && err <= ELASTERRNO)) {    switch (IsEError(err) ? OSStatus2E(err) : err) {        case EBADF:            PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);            break;        case EADDRNOTAVAIL:            PR_SetError(PR_ADDRESS_NOT_AVAILABLE_ERROR, err);            break;        case EINPROGRESS:            PR_SetError(PR_IN_PROGRESS_ERROR, err);            break;        case EWOULDBLOCK:        case EAGAIN:            PR_SetError(PR_WOULD_BLOCK_ERROR, err);            break;        case ENOTSOCK:            PR_SetError(PR_NOT_SOCKET_ERROR, err);            break;        case ETIMEDOUT:            PR_SetError(PR_IO_TIMEOUT_ERROR, err);            break;        case ECONNREFUSED:            PR_SetError(PR_CONNECT_REFUSED_ERROR, err);            break;        case ENETUNREACH:            PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, err);            break;        case EADDRINUSE:            PR_SetError(PR_ADDRESS_IN_USE_ERROR, err);            break;        case EFAULT:            PR_SetError(PR_ACCESS_FAULT_ERROR, err);            break;        case EINTR:            PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);            break;        case EINVAL:            PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);            break;        case EIO:            PR_SetError(PR_IO_ERROR, err);            break;        case ENOENT:            PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);            break;        case ENXIO:            PR_SetError(PR_IO_ERROR, err);            break;        case EPROTOTYPE:            PR_SetError(PR_PROTOCOL_NOT_SUPPORTED_ERROR, err);            break;        case EOPNOTSUPP:            PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, err);            break;        default:            PR_SetError(PR_UNKNOWN_ERROR, err);            break;        }    } else {    PR_ASSERT(IsXTIError(err));    switch (err) {        case kOTNoDataErr:        case kOTFlowErr:            PR_SetError(PR_WOULD_BLOCK_ERROR, err);            break;        default:            PR_SetError(PR_UNKNOWN_ERROR, err);            break;        }    }}static void PrepareForAsyncCompletion(PRThread * thread, PRInt32 osfd){    thread->io_pending       = PR_TRUE;    thread->io_fd            = osfd;    thread->md.osErrCode     = noErr;}voidWakeUpNotifiedThread(PRThread *thread, OTResult result){    _PRCPU *      cpu      = _PR_MD_CURRENT_CPU(); 	if (thread) {		thread->md.osErrCode = result;		if (_PR_MD_GET_INTSOFF()) {			thread->md.missedIONotify = PR_TRUE;			cpu->u.missed[cpu->where] |= _PR_MISSED_IO;		} else {			DoneWaitingOnThisThread(thread);		}	}		SignalIdleSemaphore();}// Notification routine// Async callback routine.// A5 is OK. Cannot allocate memory here// Ref: http://gemma.apple.com/techpubs/mac/NetworkingOT/NetworkingWOT-100.html//static pascal void  NotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie){    PRFilePrivate *secret  = (PRFilePrivate *) contextPtr;    _MDFileDesc * md       = &(secret->md);    EndpointRef   endpoint = (EndpointRef)secret->md.osfd;    PRThread *    readThread   = NULL;          // also used for 'misc'    PRThread *    writeThread  = NULL;    OSStatus      err;    OTResult      resultOT;    TDiscon       discon;    switch (code)    {// OTLook Events -         case T_LISTEN:        // A connection request is available            // If md->doListen is true, then PR_Listen has been            // called on this endpoint; therefore, we're ready to            // accept connections. But we'll do that with PR_Accept            // (which calls OTListen, OTAccept, etc) instead of             // doing it here.             if (md->doListen) {                readThread = secret->md.misc.thread;                secret->md.misc.thread    = NULL;                secret->md.misc.cookie    = cookie;                break;            } else {                // Reject the connection, we're not listening                OTSndDisconnect(endpoint, NULL);            }            break;        case T_CONNECT:      // Confirmation of a connect request            // cookie = sndCall parameter from OTConnect()            err = OTRcvConnect(endpoint, NULL);            PR_ASSERT(err == kOTNoError);            // wake up waiting thread, if any.            writeThread = secret->md.write.thread;            secret->md.write.thread    = NULL;            secret->md.write.cookie    = cookie;                        break;        case T_DATA:        // Standard data is available            // Mark this socket as readable.            secret->md.readReady = PR_TRUE;            // wake up waiting thread, if any            readThread = secret->md.read.thread;            secret->md.read.thread    = NULL;            secret->md.read.cookie    = cookie;            break;        case T_EXDATA:      // Expedited data is available            PR_ASSERT(!"T_EXDATA Not implemented");            return;        case T_DISCONNECT:  // A disconnect is available            discon.udata.len = 0;            err = OTRcvDisconnect(endpoint, &discon);            PR_ASSERT(err == kOTNoError);            secret->md.exceptReady = PR_TRUE;       // XXX Check this            md->disconnectError = discon.reason;    // save for _MD_mac_get_nonblocking_connect_error            // wake up waiting threads, if any            result = -3199 - discon.reason; // obtain the negative error code            if ((readThread = secret->md.read.thread) != NULL) {                secret->md.read.thread    = NULL;                secret->md.read.cookie    = cookie;            }            if ((writeThread = secret->md.write.thread) != NULL) {                secret->md.write.thread    = NULL;                secret->md.write.cookie    = cookie;            }            break;        case T_ERROR:       // obsolete/unused in library            PR_ASSERT(!"T_ERROR Not implemented");            return;        case T_UDERR:       // UDP Send error; clear the error            (void) OTRcvUDErr((EndpointRef) cookie, NULL);            break;        case T_ORDREL:      // An orderly release is available            err = OTRcvOrderlyDisconnect(endpoint);            PR_ASSERT(err == kOTNoError);            secret->md.readReady      = PR_TRUE;   // mark readable (to emulate bsd sockets)            // remember connection is closed, so we can return 0 on read or receive            secret->md.orderlyDisconnect = PR_TRUE;                        readThread = secret->md.read.thread;            secret->md.read.thread    = NULL;            secret->md.read.cookie    = cookie;            break;		        case T_GODATA:   // Flow control lifted on standard data            secret->md.writeReady = PR_TRUE;            resultOT = OTLook(endpoint);        // clear T_GODATA event            PR_ASSERT(resultOT == T_GODATA);                        // wake up waiting thread, if any            writeThread = secret->md.write.thread;            secret->md.write.thread    = NULL;            secret->md.write.cookie    = cookie;            break;        case T_GOEXDATA: // Flow control lifted on expedited data            PR_ASSERT(!"T_GOEXDATA Not implemented");            return;        case T_REQUEST:  // An Incoming request is available            PR_ASSERT(!"T_REQUEST Not implemented");            return;        case T_REPLY:    // An Incoming reply is available            PR_ASSERT(!"T_REPLY Not implemented");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -