Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Enumerations | Functions | Variables
macsockotpt.c File Reference
#include <string.h>
#include <Gestalt.h>
#include <Files.h>
#include <OpenTransport.h>
#include <OSUtils.h>
#include <OpenTptInternet.h>
#include "primpl.h"

Go to the source code of this file.

Classes

struct  RawEndpointAndThread

Defines

#define OTUNIXERRORS   1
#define GESTALT_OPEN_TPT_PRESENT   gestaltOpenTptPresentMask
#define GESTALT_OPEN_TPT_TCP_PRESENT   gestaltOpenTptTCPPresentMask
#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)
#define DESCRIPTOR_FLAGS_ARRAY_SIZE   32
#define kIPName   "ip"

Typedefs

typedef enum SndRcvOpCode SndRcvOpCode
typedef struct RawEndpointAndThread RawEndpointAndThread

Enumerations

enum  SndRcvOpCode { kSTREAM_SEND, kSTREAM_RECEIVE, kDGRAM_SEND, kDGRAM_RECEIVE }

Functions

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)
void WakeUpNotifiedThread (PRThread *thread, OTResult result)
void WaitOnThisThread (PRThread *thread, PRIntervalTime timeout)
void DoneWaitingOnThisThread (PRThread *thread)
void _MD_InitNetAccess ()
static void _MD_FinishInitNetAccess ()
static void macsock_map_error (OSStatus err)
static void PrepareForAsyncCompletion (PRThread *thread, PRInt32 osfd)
static OSErr CreateSocket (int type, EndpointRef *endpoint)
PRInt32 _MD_socket (int domain, int type, int protocol)
PRInt32 _MD_bind (PRFileDesc *fd, PRNetAddr *addr, PRUint32 addrlen)
PRInt32 _MD_listen (PRFileDesc *fd, PRIntn backlog)
PRInt32 _MD_getsockname (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
PRStatus _MD_getsockopt (PRFileDesc *fd, PRInt32 level, PRInt32 optname, char *optval, PRInt32 *optlen)
PRStatus _MD_setsockopt (PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char *optval, PRInt32 optlen)
PRInt32 _MD_socketavailable (PRFileDesc *fd)
PRInt32 _MD_accept (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
PRInt32 _MD_connect (PRFileDesc *fd, PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
static PRInt32 SendReceiveStream (PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout, SndRcvOpCode opCode)
PRInt32 _MD_recv (PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout)
PRInt32 _MD_send (PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout)
static PRInt32 SendReceiveDgram (PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout, SndRcvOpCode opCode)
PRInt32 _MD_recvfrom (PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
PRInt32 _MD_sendto (PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
PRInt32 _MD_closesocket (PRInt32 osfd)
PRInt32 _MD_writev (PRFileDesc *fd, const struct PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout)
static PRInt32 CheckPollDescMethods (PRPollDesc *pds, PRIntn npds, PRInt16 *outReadFlags, PRInt16 *outWriteFlags)
static PRInt32 CheckPollDescEndpoints (PRPollDesc *pds, PRIntn npds, const PRInt16 *inReadFlags, const PRInt16 *inWriteFlags)
static PRInt32 CountReadyPollDescs (PRPollDesc *pds, PRIntn npds)
static void SetDescPollThread (PRPollDesc *pds, PRIntn npds, PRThread *thread)
PRInt32 _MD_poll (PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
void _MD_initfiledesc (PRFileDesc *fd)
void _MD_freefiledesc (PRFileDesc *fd)
void _MD_makenonblock (PRFileDesc *fd)
void _MD_initfdinheritable (PRFileDesc *fd, PRBool imported)
void _MD_queryfdinheritable (PRFileDesc *fd)
 PR_IMPLEMENT (PRInt32)
 _MD_getpeername (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
 PR_IMPLEMENT (struct hostent *)
 PR_IMPLEMENT (char *)
PRStatus _MD_gethostname (char *name, int namelen)
 PR_IMPLEMENT (struct protoent *)
int _MD_mac_get_nonblocking_connect_error (PRFileDesc *fd)

Variables

struct {
PRLocklock
InetSvcRef serviceRef
PRThreadthread
voidcookie
dnsContext
static OTNotifyUPP DNSNotifierRoutineUPP
static OTNotifyUPP NotifierRoutineUPP
static OTNotifyUPP RawEndpointNotifierRoutineUPP
static char * sAliases [1] = {NULL}
static struct hostent = {NULL, &sAliases[0], AF_INET, sizeof (long), NULL}
static InetHostInfo sHostInfo
static InetHost * sAddresses [kMaxHostAddrs+1]
static struct protoent = {kIPName, NULL, INET_IP}

Class Documentation

struct RawEndpointAndThread

Definition at line 1082 of file macsockotpt.c.

Collaboration diagram for RawEndpointAndThread:
Class Members
EndpointRef endpoint
PRThread * thread

Define Documentation

Definition at line 1929 of file macsockotpt.c.

#define GESTALT_OPEN_TPT_PRESENT   gestaltOpenTptPresentMask

Definition at line 48 of file macsockotpt.c.

#define GESTALT_OPEN_TPT_TCP_PRESENT   gestaltOpenTptTCPPresentMask

Definition at line 49 of file macsockotpt.c.

#define INIT_OPEN_TRANSPORT ( )    InitOpenTransport()

Definition at line 96 of file macsockotpt.c.

#define kIPName   "ip"

Definition at line 2254 of file macsockotpt.c.

#define OT_OPEN_ENDPOINT (   config,
  flags,
  info,
  err 
)    OTOpenEndpoint(config, flags, info, err)

Definition at line 98 of file macsockotpt.c.

#define OT_OPEN_INTERNET_SERVICES (   config,
  flags,
  err 
)    OTOpenInternetServices(config, flags, err)

Definition at line 97 of file macsockotpt.c.

Definition at line 39 of file macsockotpt.c.


Typedef Documentation

typedef enum SndRcvOpCode SndRcvOpCode

Enumeration Type Documentation

Enumerator:
kSTREAM_SEND 
kSTREAM_RECEIVE 
kDGRAM_SEND 
kDGRAM_RECEIVE 

Definition at line 60 of file macsockotpt.c.


Function Documentation

PRInt32 _MD_accept ( PRFileDesc fd,
PRNetAddr addr,
PRUint32 addrlen,
PRIntervalTime  timeout 
)

Definition at line 1190 of file macsockotpt.c.

{
    OSStatus err;
    EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
    PRThread *me = _PR_MD_CURRENT_THREAD();
    TBind bindReq;
    PRNetAddr bindAddr;
    PRInt32 newosfd = -1;
    TCall call;
    PRNetAddr callAddr;
    RawEndpointAndThread *endthr = NULL;

    if (endpoint == NULL) {
        err = kEBADFErr;
        goto ErrorExit;
    }
        
    memset(&call, 0 , sizeof(call));

    if (addr != NULL) {
        call.addr.maxlen = *addrlen;
        call.addr.len = *addrlen;
        call.addr.buf = (UInt8*) addr;
    } else {
        call.addr.maxlen = sizeof(callAddr);
        call.addr.len = sizeof(callAddr);
        call.addr.buf = (UInt8*) &callAddr;
    }

       do {
           PrepareForAsyncCompletion(me, fd->secret->md.osfd);
           fd->secret->md.misc.thread = me;
           
           // Perform the listen. 
           err = OTListen (endpoint, &call);
           if (err == kOTNoError)
              break; // got the call information
           else if ((!fd->secret->nonblocking) && (err == kOTNoDataErr)) {
               WaitOnThisThread(me, timeout);
               err = me->md.osErrCode;
               if ((err != kOTNoError) && (err != kOTNoDataErr))
                     goto ErrorExit;
                     // we can get kOTNoError here, but still need
                     // to loop back to call OTListen, in order
                     // to get call info for OTAccept
           } else {
              goto ErrorExit; // we're nonblocking, and/or we got an error
           }   
       }
       while(1);

    newosfd = _MD_socket(AF_INET, SOCK_STREAM, 0);
    if (newosfd == -1)
        return -1;
            
       // Attach the raw endpoint handler to this endpoint for now.
       endthr = (RawEndpointAndThread *) PR_Malloc(sizeof(RawEndpointAndThread));
       endthr->thread = me;
       endthr->endpoint = (EndpointRef) newosfd;
       
       err = OTInstallNotifier((ProviderRef) newosfd, RawEndpointNotifierRoutineUPP, endthr);
    PR_ASSERT(err == kOTNoError);
    
       err = OTSetAsynchronous((EndpointRef) newosfd);
       PR_ASSERT(err == kOTNoError);

    // Bind to a local port; let the system assign it.
    bindAddr.inet.family = AF_INET;
    bindAddr.inet.port = bindAddr.inet.ip = 0;

    bindReq.addr.maxlen = PR_NETADDR_SIZE (&bindAddr);
    bindReq.addr.len = 0;
    bindReq.addr.buf = (UInt8*) &bindAddr;
    bindReq.qlen = 0;

    PrepareForAsyncCompletion(me, newosfd);    
    err = OTBind((EndpointRef) newosfd, &bindReq, NULL);
    if (err != kOTNoError)
        goto ErrorExit;

    WaitOnThisThread(me, timeout);

    err = me->md.osErrCode;
    if (err != kOTNoError)
        goto ErrorExit;

    PrepareForAsyncCompletion(me, newosfd);    

    err = OTAccept (endpoint, (EndpointRef) newosfd, &call);
       if ((err != kOTNoError) && (err != kOTNoDataErr))
        goto ErrorExit;

    WaitOnThisThread(me, timeout);

    err = me->md.osErrCode;
    if (err != kOTNoError)
        goto ErrorExit;

    if (addrlen != NULL)
        *addrlen = call.addr.len;

       // Remove the temporary notifier we installed to set up the new endpoint.
       OTRemoveNotifier((EndpointRef) newosfd);
       PR_Free(endthr); // free the temporary context we set up for this endpoint

    return newosfd;

ErrorExit:
       me->io_pending = PR_FALSE; // clear pending wait state if any
    if (newosfd != -1)
        _MD_closesocket(newosfd);
    macsock_map_error(err);
    return -1;
}

Here is the call graph for this function:

PRInt32 _MD_bind ( PRFileDesc fd,
PRNetAddr addr,
PRUint32  addrlen 
)

Definition at line 580 of file macsockotpt.c.

{
    OSStatus err;
    EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
    TBind bindReq;
    PRThread *me = _PR_MD_CURRENT_THREAD();
    PRUint32 retryCount = 0;

    if (endpoint == NULL) {
        err = kEBADFErr;
        goto ErrorExit;
    }
        
    if (addr == NULL) {
        err = kEFAULTErr;
        goto ErrorExit;
    }
        
/*
 * There seems to be a bug with OT related to OTBind failing with kOTNoAddressErr even though
 * a proper legal address was supplied.  This happens very rarely and just retrying the
 * operation after a certain time (less than 1 sec. does not work) seems to succeed.
 */

TryAgain:
    // setup our request
    bindReq.addr.len = addrlen;
        
    bindReq.addr.maxlen = addrlen;
    bindReq.addr.buf = (UInt8*) addr;
    bindReq.qlen = 1;

       PR_Lock(fd->secret->md.miscLock);
    PrepareForAsyncCompletion(me, fd->secret->md.osfd);
       fd->secret->md.misc.thread = me;

    err = OTBind(endpoint, &bindReq, NULL);
    if (err != kOTNoError) {
           me->io_pending = PR_FALSE;
           PR_Unlock(fd->secret->md.miscLock);
        goto ErrorExit;
       }

    WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
       PR_Unlock(fd->secret->md.miscLock);

    err = me->md.osErrCode;
    if (err != kOTNoError)
        goto ErrorExit;

    return kOTNoError;

ErrorExit:
    if ((err == kOTNoAddressErr) && (++retryCount <= 4)) {
        unsigned long finalTicks;
    
        Delay(100,&finalTicks);
        goto TryAgain;
    }
    macsock_map_error(err);
    return -1;
}

Here is the call graph for this function:

Definition at line 1685 of file macsockotpt.c.

{
    OSStatus err;
    EndpointRef endpoint = (EndpointRef) osfd;
    PRThread *me = _PR_MD_CURRENT_THREAD();

    if (endpoint == NULL) {
        err = kEBADFErr;
        goto ErrorExit;
    }
        
    if (me->io_pending && me->io_fd == osfd)
        me->io_pending = PR_FALSE;

    (void) OTSndOrderlyDisconnect(endpoint);
    err = OTCloseProvider(endpoint);
    if (err != kOTNoError)
        goto ErrorExit;

    return kOTNoError;

ErrorExit:
    macsock_map_error(err);
    return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRInt32 _MD_connect ( PRFileDesc fd,
PRNetAddr addr,
PRUint32  addrlen,
PRIntervalTime  timeout 
)

Definition at line 1306 of file macsockotpt.c.

{
    OSStatus err;
    EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
    PRThread *me = _PR_MD_CURRENT_THREAD();
    TCall sndCall;
    TBind bindReq;
    PRNetAddr bindAddr;

    if (endpoint == NULL) {
        err = kEBADFErr;
        goto ErrorExit;
    }
        
    if (addr == NULL) {
        err = kEFAULTErr;
        goto ErrorExit;
    }
    
    // Bind to a local port; let the system assign it.

    bindAddr.inet.family = AF_INET;
    bindAddr.inet.port = bindAddr.inet.ip = 0;

    bindReq.addr.maxlen = PR_NETADDR_SIZE (&bindAddr);
    bindReq.addr.len = 0;
    bindReq.addr.buf = (UInt8*) &bindAddr;
    bindReq.qlen = 0;
    
    PR_Lock(fd->secret->md.miscLock);
    PrepareForAsyncCompletion(me, fd->secret->md.osfd);    
    fd->secret->md.misc.thread = me;

    err = OTBind(endpoint, &bindReq, NULL);
    if (err != kOTNoError) {
      me->io_pending = PR_FALSE;
      PR_Unlock(fd->secret->md.miscLock);
      goto ErrorExit;
    }

    WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
    PR_Unlock(fd->secret->md.miscLock);

    err = me->md.osErrCode;
    if (err != kOTNoError)
        goto ErrorExit;

    memset(&sndCall, 0 , sizeof(sndCall));

    sndCall.addr.maxlen = addrlen;
    sndCall.addr.len = addrlen;
    sndCall.addr.buf = (UInt8*) addr;

    if (!fd->secret->nonblocking) {    
      PrepareForAsyncCompletion(me, fd->secret->md.osfd);
      PR_ASSERT(fd->secret->md.write.thread == NULL);
      fd->secret->md.write.thread = me;
    }

    err = OTConnect (endpoint, &sndCall, NULL);
    if (err == kOTNoError) {
      PR_ASSERT(!"OTConnect returned kOTNoError in async mode!?!");   
    }
    if (fd->secret->nonblocking) {
      if (err == kOTNoDataErr)
      err = EINPROGRESS;
      goto ErrorExit;
    } else {
      if (err != kOTNoError && err != kOTNoDataErr) {
        me->io_pending = PR_FALSE;
        goto ErrorExit;
      }
    }
       
    WaitOnThisThread(me, timeout);

    err = me->md.osErrCode;
    if (err != kOTNoError)
        goto ErrorExit;

    return kOTNoError;

ErrorExit:
    macsock_map_error(err);
    return -1;
}

Here is the call graph for this function:

static void _MD_FinishInitNetAccess ( ) [static]

Definition at line 141 of file macsockotpt.c.

{
    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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2023 of file macsockotpt.c.

Here is the call graph for this function:

PRStatus _MD_gethostname ( char *  name,
int  namelen 
)

Definition at line 2219 of file macsockotpt.c.

{
    OSStatus err;
    InetInterfaceInfo info;

    _MD_FinishInitNetAccess();

    /*
     *    On a Macintosh, we don't have the concept of a local host name.
     *    We do though have an IP address & everyone should be happy with
     *     a string version of that for a name.
     *    The alternative here is to ping a local DNS for our name, they
     *    will often know it.  This is the cheap, easiest, and safest way out.
     */

    /* Make sure the string is as long as the longest possible address */
    if (namelen < strlen("123.123.123.123")) {
        err = kEINVALErr;
        goto ErrorExit;
    }

    err = OTInetGetInterfaceInfo(&info, kDefaultInetInterface);
    if (err != kOTNoError)
        goto ErrorExit;
    
    OTInetHostToString(info.fAddress, name);
    
    return PR_SUCCESS;

ErrorExit:
    macsock_map_error(err);
    return PR_FAILURE;
}

Here is the call graph for this function:

_MD_getpeername ( PRFileDesc fd,
PRNetAddr addr,
PRUint32 addrlen 
)

Definition at line 2085 of file macsockotpt.c.

{
    PRThread *me = _PR_MD_CURRENT_THREAD();
       EndpointRef ep = (EndpointRef) fd->secret->md.osfd;
       InetAddress inetAddr;
       TBind peerAddr;
       OSErr err;
       
       if (*addrlen < sizeof(InetAddress)) {

              err = (OSErr) kEINVALErr;
              goto ErrorExit;
       }

    peerAddr.addr.maxlen = sizeof(InetAddress);
    peerAddr.addr.len = 0;
    peerAddr.addr.buf = (UInt8*) &inetAddr;
    peerAddr.qlen = 0;

    PrepareForAsyncCompletion(me, fd->secret->md.osfd);    
       fd->secret->md.misc.thread = me; // tell notifier routine what to wake up

       err = OTGetProtAddress(ep, NULL, &peerAddr);
       
    if (err != kOTNoError)
        goto ErrorExit;

    WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);

    err = me->md.osErrCode;
    if ((err == kOTNoError) && (peerAddr.addr.len < sizeof(InetAddress)))
       err = kEBADFErr; // we don't understand the address we got
    if (err != kOTNoError)
       goto ErrorExit;
       
    // Translate the OT peer information into an NSPR address.
    addr->inet.family = AF_INET;
    addr->inet.port = (PRUint16) inetAddr.fPort;
    addr->inet.ip = (PRUint32) inetAddr.fHost;
    
    *addrlen = PR_NETADDR_SIZE(addr); // return the amount of data obtained
       return PR_SUCCESS;

ErrorExit:
    macsock_map_error(err);
    return PR_FAILURE;
}

Here is the call graph for this function:

PRInt32 _MD_getsockname ( PRFileDesc fd,
PRNetAddr addr,
PRUint32 addrlen 
)

Definition at line 735 of file macsockotpt.c.

{
    OSStatus err;
    EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
    TBind bindReq;
    PRThread *me = _PR_MD_CURRENT_THREAD();

    if (endpoint == NULL) {
        err = kEBADFErr;
        goto ErrorExit;
    }
        
    if (addr == NULL) {
        err = kEFAULTErr;
        goto ErrorExit;
    }

    bindReq.addr.len = *addrlen;
    bindReq.addr.maxlen = *addrlen;
    bindReq.addr.buf = (UInt8*) addr;
    bindReq.qlen = 0;
    
       PR_Lock(fd->secret->md.miscLock);
    PrepareForAsyncCompletion(me, fd->secret->md.osfd);    
       fd->secret->md.misc.thread = me;

    err = OTGetProtAddress(endpoint, &bindReq, NULL);
    if (err != kOTNoError) {
           me->io_pending = PR_FALSE;
           PR_Unlock(fd->secret->md.miscLock);
        goto ErrorExit;
       }

    WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
       PR_Unlock(fd->secret->md.miscLock);

    err = me->md.osErrCode;
    if (err != kOTNoError)
        goto ErrorExit;

    *addrlen = PR_NETADDR_SIZE(addr);
    return kOTNoError;

ErrorExit:
    macsock_map_error(err);
    return -1;
}

Here is the call graph for this function:

PRStatus _MD_getsockopt ( PRFileDesc fd,
PRInt32  level,
PRInt32  optname,
char *  optval,
PRInt32 optlen 
)

Definition at line 784 of file macsockotpt.c.

{
    OSStatus err;
    EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
    TOptMgmt cmd;
    TOption *opt;
    PRThread *me = _PR_MD_CURRENT_THREAD();
    unsigned char optionBuffer[kOTOptionHeaderSize + sizeof(PRSocketOptionData)];
    
    if (endpoint == NULL) {
        err = kEBADFErr;
        goto ErrorExit;
    }
    
    /* 
    OT wants IPPROTO_IP for level and not XTI_GENERIC.  SO_REUSEADDR and SO_KEEPALIVE 
    are equated to IP level and TCP level options respectively and hence we need to set 
    the level correctly.
    */
    if (level == SOL_SOCKET) {
        if (optname == SO_REUSEADDR)
            level = IPPROTO_IP;
        else if (optname == SO_KEEPALIVE)
            level = INET_TCP;
    }

    opt = (TOption *)&optionBuffer[0];
    opt->len = sizeof(TOption);
    opt->level = level;
    opt->name = optname;
    opt->status = 0;
    
    cmd.opt.len = sizeof(TOption);
    cmd.opt.maxlen = sizeof(optionBuffer);
    cmd.opt.buf = (UInt8*)optionBuffer;
    cmd.flags = T_CURRENT;

       PR_Lock(fd->secret->md.miscLock);
    PrepareForAsyncCompletion(me, fd->secret->md.osfd);    
       fd->secret->md.misc.thread = me;

    err = OTOptionManagement(endpoint, &cmd, &cmd);
    if (err != kOTNoError) {
           me->io_pending = PR_FALSE;
           PR_Unlock(fd->secret->md.miscLock);
        goto ErrorExit;
       }

    WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
       PR_Unlock(fd->secret->md.miscLock);

    err = me->md.osErrCode;
    if (err != kOTNoError)
        goto ErrorExit;

    if (opt->status == T_FAILURE || opt->status == T_NOTSUPPORT){
        err = kEOPNOTSUPPErr;
        goto ErrorExit;
    }

    PR_ASSERT(opt->status == T_SUCCESS);

    switch (optname) {
        case SO_LINGER:
            *((t_linger*)optval) = *((t_linger*)&opt->value);
            *optlen = sizeof(t_linger);
            break;
        case SO_REUSEADDR:
        case TCP_NODELAY:
        case SO_KEEPALIVE:
        case SO_RCVBUF:
        case SO_SNDBUF:
            *((PRIntn*)optval) = *((PRIntn*)&opt->value);
            *optlen = sizeof(PRIntn);
            break;
        case IP_MULTICAST_LOOP:
            *((PRUint8*)optval) = *((PRIntn*)&opt->value);
            *optlen = sizeof(PRUint8);
            break;
        case IP_TTL:
            *((PRUintn*)optval) = *((PRUint8*)&opt->value);
            *optlen = sizeof(PRUintn);
            break;
        case IP_MULTICAST_TTL:
            *((PRUint8*)optval) = *((PRUint8*)&opt->value);
            *optlen = sizeof(PRUint8);
            break;
        case IP_ADD_MEMBERSHIP:
        case IP_DROP_MEMBERSHIP:
            {
            /* struct ip_mreq and TIPAddMulticast are the same size and optval 
               is pointing to struct ip_mreq */
            *((struct ip_mreq *)optval) = *((struct ip_mreq *)&opt->value);
            *optlen = sizeof(struct ip_mreq);
            break;
            }
        case IP_MULTICAST_IF:
            {
            *((PRUint32*)optval) = *((PRUint32*)&opt->value);
            *optlen = sizeof(PRUint32);
            break;
            }
        /*case IP_TOS:*/ /*IP_TOS has same value as TCP_MAXSEG */
        case TCP_MAXSEG:
            if (level == IPPROTO_TCP) { /* it is TCP_MAXSEG */
                *((PRIntn*)optval) = *((PRIntn*)&opt->value);
                *optlen = sizeof(PRIntn);
            } else { /* it is IP_TOS */
                *((PRUintn*)optval) = *((PRUint8*)&opt->value);
                *optlen = sizeof(PRUintn);
            }
            break;
        default:
            PR_ASSERT(0);
            break;    
    }
    
    return PR_SUCCESS;

ErrorExit:
    macsock_map_error(err);
    return PR_FAILURE;
}

Here is the call graph for this function:

void _MD_initfdinheritable ( PRFileDesc fd,
PRBool  imported 
)

Definition at line 2061 of file macsockotpt.c.

{
       /* XXX this function needs to be implemented */
       fd->secret->inheritable = _PR_TRI_UNKNOWN;
}

Definition at line 2004 of file macsockotpt.c.

{
       // Allocate a PR_Lock to arbitrate miscellaneous OT calls for this endpoint between threads
       // We presume that only one thread will be making Read calls (Recv/Accept) and that only
       // one thread will be making Write calls (Send/Connect) on the endpoint at a time.
       if (fd->methods->file_type == PR_DESC_SOCKET_TCP ||
              fd->methods->file_type == PR_DESC_SOCKET_UDP )
       {
              PR_ASSERT(fd->secret->md.miscLock == NULL);
              fd->secret->md.miscLock = PR_NewLock();
              PR_ASSERT(fd->secret->md.miscLock != NULL);
              fd->secret->md.orderlyDisconnect = PR_FALSE;
              fd->secret->md.readReady = PR_FALSE;             // let's not presume we have data ready to read
              fd->secret->md.writeReady = PR_TRUE;             // let's presume we can write unless we hear otherwise
              fd->secret->md.exceptReady = PR_FALSE;
       }
}

Here is the call graph for this function:

Definition at line 105 of file macsockotpt.c.

{
    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! */
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRInt32 _MD_listen ( PRFileDesc fd,
PRIntn  backlog 
)

Definition at line 646 of file macsockotpt.c.

{
    PRInt32 osfd = fd->secret->md.osfd;
    OSStatus err = 0;
    EndpointRef endpoint = (EndpointRef) osfd;
    TBind bindReq;
    PRNetAddr addr;
    PRThread *me = _PR_MD_CURRENT_THREAD();

       if ((fd == NULL) || (endpoint == NULL)) {
              err = EBADF;
              goto ErrorExit;
       }

    if (backlog == 0)
        backlog = 1;

    if (endpoint == NULL) {
        err = EBADF;
        goto ErrorExit;
    }
        
    addr.inet.family = AF_INET;
    addr.inet.port = addr.inet.ip = 0;

    bindReq.addr.maxlen = PR_NETADDR_SIZE (&addr);
    bindReq.addr.len = 0;
    bindReq.addr.buf = (UInt8*) &addr;
    bindReq.qlen = 0;
    
    PrepareForAsyncCompletion(me, fd->secret->md.osfd);    
       fd->secret->md.misc.thread = me; // tell notifier routine what to wake up

    err = OTGetProtAddress(endpoint, &bindReq, NULL);
    if (err != kOTNoError)
        goto ErrorExit;

    WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);

    err = me->md.osErrCode;
    if (err != kOTNoError)
        goto ErrorExit;

    PrepareForAsyncCompletion(me, fd->secret->md.osfd);    
       fd->secret->md.misc.thread = me; // tell notifier routine what to wake up

    err = OTUnbind(endpoint);
    if (err != kOTNoError)
        goto ErrorExit;

    WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);

    err = me->md.osErrCode;
    if (err != kOTNoError)
        goto ErrorExit;

       /* tell the notifier func that we are interested in pending connections */
       fd->secret->md.doListen = PR_TRUE;
       /* accept up to (backlog) pending connections at any one time */
    bindReq.qlen = backlog;
    
    PrepareForAsyncCompletion(me, fd->secret->md.osfd);    
       fd->secret->md.misc.thread = me; // tell notifier routine what to wake up

    err = OTBind(endpoint, &bindReq, NULL);
    if (err != kOTNoError)
        goto ErrorExit;

    WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);

    err = me->md.osErrCode;
    if (err != kOTNoError)
    {
       // If OTBind failed, we're really not ready to listen after all.
              fd->secret->md.doListen = PR_FALSE;
        goto ErrorExit;
    }

    return kOTNoError;

ErrorExit:
       me->io_pending = PR_FALSE; // clear pending wait state if any
    macsock_map_error(err);
    return -1;
}

Here is the call graph for this function:

Definition at line 2293 of file macsockotpt.c.

{
    EndpointRef endpoint = (EndpointRef)fd->secret->md.osfd;
    OTResult    resultOT = OTGetEndpointState(endpoint);

    switch (resultOT)    {
        case T_OUTCON:
            macsock_map_error(EINPROGRESS);
            return -1;
            
        case T_DATAXFER:
            return 0;
            
        case T_IDLE:
            macsock_map_error(fd->secret->md.disconnectError);
            fd->secret->md.disconnectError = 0;
            return -1;

        case T_INREL:
            macsock_map_error(ENOTCONN);
            return -1;

        default:
            PR_ASSERT(0);
            return -1;
    }

    return -1;      // not reached
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2037 of file macsockotpt.c.

{
       // We simulate non-blocking mode using async mode rather
       // than put the endpoint in non-blocking mode.
       // We need to install the PRFileDesc as the contextPtr for the NotifierRoutine, but it
       // didn't exist at the time the endpoint was created.  It does now though...
       ProviderRef   endpointRef = (ProviderRef)fd->secret->md.osfd;
       OSStatus      err;
       
       // Install fd->secret as the contextPtr for the Notifier function associated with this 
       // endpoint. We use this instead of the fd itself because:
       //            (a) in cases where you import I/O layers, the containing 
       //                fd changes, but the secret structure does not;
       //            (b) the notifier func refers only to the secret data structure
       //                anyway.
       err = OTInstallNotifier(endpointRef, NotifierRoutineUPP, fd->secret);
       PR_ASSERT(err == kOTNoError);
       
       // Now that we have a NotifierRoutine installed, we can make the endpoint asynchronous
       err = OTSetAsynchronous(endpointRef);
       PR_ASSERT(err == kOTNoError);
}

Here is the call graph for this function:

PRInt32 _MD_poll ( PRPollDesc pds,
PRIntn  npds,
PRIntervalTime  timeout 
)

Definition at line 1931 of file macsockotpt.c.

{
    PRInt16     readFlagsArray[DESCRIPTOR_FLAGS_ARRAY_SIZE];
    PRInt16     writeFlagsArray[DESCRIPTOR_FLAGS_ARRAY_SIZE];
    
    PRInt16     *readFlags  = readFlagsArray;
    PRInt16     *writeFlags = writeFlagsArray;

    PRInt16     *ioFlags = NULL;
    
    PRThread    *thread = _PR_MD_CURRENT_THREAD();
    PRInt32     ready;
    
    if (npds > DESCRIPTOR_FLAGS_ARRAY_SIZE)
    {
        // we allocate a single double-size array. The first half is used
        // for read flags, and the second half for write flags.
        ioFlags = (PRInt16*)PR_Malloc(sizeof(PRInt16) * npds * 2);
        if (!ioFlags)
        {
            PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
            return -1;
        }
        
        readFlags = ioFlags;
        writeFlags = &ioFlags[npds];
    }

    // we have to be outside the lock when calling this, since
    // it can call arbitrary user code (including other socket
    // entry points)
    ready = CheckPollDescMethods(pds, npds, readFlags, writeFlags);

    if (!ready && timeout != PR_INTERVAL_NO_WAIT) {
        intn        is;
        

        _PR_INTSOFF(is);
        PR_Lock(thread->md.asyncIOLock);
        PrepareForAsyncCompletion(thread, 0);

        SetDescPollThread(pds, npds, thread);

        (void)CheckPollDescEndpoints(pds, npds, readFlags, writeFlags);

        PR_Unlock(thread->md.asyncIOLock);
        _PR_FAST_INTSON(is);

        ready = CountReadyPollDescs(pds, npds);

        if (ready == 0) {
            WaitOnThisThread(thread, timeout);

            // since we may have been woken by a pollable event firing,
            // we have to check both poll methods and endpoints.
            (void)CheckPollDescMethods(pds, npds, readFlags, writeFlags);
            ready = CheckPollDescEndpoints(pds, npds, readFlags, writeFlags);
        }
        
        thread->io_pending = PR_FALSE;
        SetDescPollThread(pds, npds, NULL);
    }
    else {
        ready = CheckPollDescEndpoints(pds, npds, readFlags, writeFlags);
    }

    if (readFlags != readFlagsArray)
        PR_Free(ioFlags);
    
    return ready;
}

Here is the call graph for this function:

Definition at line 2068 of file macsockotpt.c.

{
       /* XXX this function needs to be implemented */
       PR_ASSERT(0);
}
PRInt32 _MD_recv ( PRFileDesc fd,
void buf,
PRInt32  amount,
PRIntn  flags,
PRIntervalTime  timeout 
)

Definition at line 1572 of file macsockotpt.c.

Here is the call graph for this function:

PRInt32 _MD_recvfrom ( PRFileDesc fd,
void buf,
PRInt32  amount,
PRIntn  flags,
PRNetAddr addr,
PRUint32 addrlen,
PRIntervalTime  timeout 
)

Definition at line 1667 of file macsockotpt.c.

Here is the call graph for this function:

PRInt32 _MD_send ( PRFileDesc fd,
const void buf,
PRInt32  amount,
PRIntn  flags,
PRIntervalTime  timeout 
)

Definition at line 1579 of file macsockotpt.c.

{
    return (SendReceiveStream(fd, (void *)buf, amount, flags, timeout, kSTREAM_SEND));
}

Here is the call graph for this function:

PRInt32 _MD_sendto ( PRFileDesc fd,
const void buf,
PRInt32  amount,
PRIntn  flags,
PRNetAddr addr,
PRUint32  addrlen,
PRIntervalTime  timeout 
)

Definition at line 1676 of file macsockotpt.c.

{
    return (SendReceiveDgram(fd, (void *)buf, amount, flags, addr, &addrlen,
                            timeout, kDGRAM_SEND));
}

Here is the call graph for this function:

PRStatus _MD_setsockopt ( PRFileDesc fd,
PRInt32  level,
PRInt32  optname,
const char *  optval,
PRInt32  optlen 
)

Definition at line 909 of file macsockotpt.c.

{
    OSStatus err;
    EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
    TOptMgmt cmd;
    TOption *opt;
    PRThread *me = _PR_MD_CURRENT_THREAD();
    unsigned char optionBuffer[kOTOptionHeaderSize + sizeof(PRSocketOptionData) + 1];
    
    if (endpoint == NULL) {
        err = kEBADFErr;
        goto ErrorExit;
    }
    
    /* 
    OT wants IPPROTO_IP for level and not XTI_GENERIC.  SO_REUSEADDR and SO_KEEPALIVE 
    are equated to IP level and TCP level options respectively and hence we need to set 
    the level correctly.
    */
    if (level == SOL_SOCKET) {
        if (optname == SO_REUSEADDR)
            level = IPPROTO_IP;
        else if (optname == SO_KEEPALIVE)
            level = INET_TCP;
    }

    opt = (TOption *)&optionBuffer[0];
    opt->len = kOTOptionHeaderSize + optlen;

    /* special case adjustments for length follow */
    if (optname == SO_KEEPALIVE) /* we need to pass the timeout value for OT */
        opt->len = kOTOptionHeaderSize + sizeof(t_kpalive);
    if (optname == IP_MULTICAST_TTL || optname == IP_TTL) /* it is an unsigned char value */
        opt->len = kOTOneByteOptionSize;
    if (optname == IP_TOS && level == IPPROTO_IP)
        opt->len = kOTOneByteOptionSize;

    opt->level = level;
    opt->name = optname;
    opt->status = 0;
    
    cmd.opt.len = opt->len;
    cmd.opt.maxlen = sizeof(optionBuffer);
    cmd.opt.buf = (UInt8*)optionBuffer;
    
    optionBuffer[opt->len] = 0;
    
    cmd.flags = T_NEGOTIATE;

    switch (optname) {
        case SO_LINGER:
            *((t_linger*)&opt->value) = *((t_linger*)optval);
            break;
        case SO_REUSEADDR:
        case TCP_NODELAY:
        case SO_RCVBUF:
        case SO_SNDBUF:
            *((PRIntn*)&opt->value) = *((PRIntn*)optval);
            break;
        case IP_MULTICAST_LOOP:
            if (*optval != 0)
                opt->value[0] = T_YES;
            else
                opt->value[0] = T_NO;
            break;
        case SO_KEEPALIVE:
            {
            t_kpalive *kpalive = (t_kpalive *)&opt->value;
            
            kpalive->kp_onoff = *((long*)optval);
            kpalive->kp_timeout = 10; /* timeout in minutes */
            break;
            }
        case IP_TTL:
            *((unsigned char*)&opt->value) = *((PRUintn*)optval);
            break;
        case IP_MULTICAST_TTL:
            *((unsigned char*)&opt->value) = *optval;
            break;
        case IP_ADD_MEMBERSHIP:
        case IP_DROP_MEMBERSHIP:
            {
            /* struct ip_mreq and TIPAddMulticast are the same size and optval 
               is pointing to struct ip_mreq */
            *((TIPAddMulticast *)&opt->value) = *((TIPAddMulticast *)optval);
            break;
            }
        case IP_MULTICAST_IF:
            {
            *((PRUint32*)&opt->value) = *((PRUint32*)optval);
            break;
            }
        /*case IP_TOS:*/ /*IP_TOS has same value as TCP_MAXSEG */
        case TCP_MAXSEG:
            if (level == IPPROTO_TCP) { /* it is TCP_MAXSEG */
                *((PRIntn*)&opt->value) = *((PRIntn*)optval);
            } else { /* it is IP_TOS */
                *((unsigned char*)&opt->value) = *((PRUintn*)optval);
            }
            break;
        default:
            PR_ASSERT(0);
            break;    
    }
    
       PR_Lock(fd->secret->md.miscLock);
    PrepareForAsyncCompletion(me, fd->secret->md.osfd);    
       fd->secret->md.misc.thread = me;

    err = OTOptionManagement(endpoint, &cmd, &cmd);
    if (err != kOTNoError) {
           me->io_pending = PR_FALSE;
           PR_Unlock(fd->secret->md.miscLock);
        goto ErrorExit;
       }

    WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
       PR_Unlock(fd->secret->md.miscLock);

    err = me->md.osErrCode;
    if (err != kOTNoError)
        goto ErrorExit;

    if (opt->status == T_FAILURE || opt->status == T_NOTSUPPORT){
        err = kEOPNOTSUPPErr;
        goto ErrorExit;
    }
    
    if (level == IPPROTO_TCP && optname == TCP_MAXSEG && opt->status == T_READONLY) {
        err = kEOPNOTSUPPErr;
        goto ErrorExit;
    }

    PR_ASSERT(opt->status == T_SUCCESS);

    return PR_SUCCESS;

ErrorExit:
    macsock_map_error(err);
    return PR_FAILURE;
}

Here is the call graph for this function:

PRInt32 _MD_socket ( int  domain,
int  type,
int  protocol 
)

Definition at line 523 of file macsockotpt.c.

{
    OSStatus    err;
    EndpointRef endpoint;
    
    _MD_FinishInitNetAccess();

    // We only deal with internet domain
    if (domain != AF_INET) {
        err = kEPROTONOSUPPORTErr;
        goto ErrorExit;
    }
    
    // We only know about tcp & udp
    if ((type != SOCK_STREAM) && (type != SOCK_DGRAM)) {
        err = kEPROTONOSUPPORTErr;
        goto ErrorExit;
    }
    
    // Convert default types to specific types.
    if (protocol == 0)  {
        if (type == SOCK_DGRAM)
            protocol = IPPROTO_UDP;
        else if (type == SOCK_STREAM)
            protocol = IPPROTO_TCP;
    }
    
    // Only support default protocol for tcp
    if ((type == SOCK_STREAM)  && (protocol != IPPROTO_TCP)) {
        err = kEPROTONOSUPPORTErr;
        goto ErrorExit;
    }
                
    // Only support default protocol for udp
    if ((type == SOCK_DGRAM)  && (protocol != IPPROTO_UDP)) {
        err = kEPROTONOSUPPORTErr;
        goto ErrorExit;
    }
        
    // Create a socket, we might run out of memory
    err = CreateSocket(type, &endpoint);
    if (err != kOTNoError)
        goto ErrorExit;

    PR_ASSERT((PRInt32)endpoint != -1);

    return ((PRInt32)endpoint);

ErrorExit:
    macsock_map_error(err);
    return -1;
}

Here is the call graph for this function:

Definition at line 1052 of file macsockotpt.c.

{
    PRInt32 osfd = fd->secret->md.osfd;
    OSStatus err;
    EndpointRef endpoint = (EndpointRef) osfd;
    size_t bytes;

    if (endpoint == NULL) {
        err = kEBADFErr;
        goto ErrorExit;
    }
    
    bytes = 0;
    
    err = OTCountDataBytes(endpoint, &bytes);
    if ((err == kOTLookErr) ||         // Not really errors, we just need to do a read,
        (err == kOTNoDataErr))        // or there's nothing there.
        err = kOTNoError;
        
    if (err != kOTNoError)
        goto ErrorExit;
        
    return bytes;

ErrorExit:
    macsock_map_error(err);
    return -1;
}

Here is the call graph for this function:

PRInt32 _MD_writev ( PRFileDesc fd,
const struct PRIOVec iov,
PRInt32  iov_size,
PRIntervalTime  timeout 
)

Definition at line 1712 of file macsockotpt.c.

{
#pragma unused (fd, iov, iov_size, timeout)

    PR_ASSERT(0);
    _PR_MD_CURRENT_THREAD()->md.osErrCode = unimpErr;
    return -1;
}

Here is the caller graph for this function:

static PRInt32 CheckPollDescEndpoints ( PRPollDesc pds,
PRIntn  npds,
const PRInt16 inReadFlags,
const PRInt16 inWriteFlags 
) [static]

Definition at line 1814 of file macsockotpt.c.

{
    PRInt32 ready = 0;
    PRPollDesc *pd, *epd;
    const PRInt16   *readFlag, *writeFlag;
    
    for (pd = pds, epd = pd + npds, readFlag = inReadFlags, writeFlag = inWriteFlags;
         pd < epd;
        pd++, readFlag++, writeFlag++)
    {
        PRFileDesc *bottomFD;
        PRBool      readReady, writeReady, exceptReady;
        PRInt16     in_flags_read = *readFlag;
        PRInt16     in_flags_write = *writeFlag;

        if (NULL == pd->fd || pd->in_flags == 0) continue;

        if ((pd->in_flags & ~pd->out_flags) == 0) {
            ready++;
            continue;
        }

        bottomFD = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
        /* bottomFD can be NULL for pollable sockets */
        if (bottomFD)
        {
            if (_PR_FILEDESC_OPEN == bottomFD->secret->state)
            {
                if (GetState(bottomFD, &readReady, &writeReady, &exceptReady))
                {
                    if (readReady)
                    {
                        if (in_flags_read & PR_POLL_READ)
                            pd->out_flags |= PR_POLL_READ;
                        if (in_flags_write & PR_POLL_READ)
                            pd->out_flags |= PR_POLL_WRITE;
                    }
                    if (writeReady)
                    {
                        if (in_flags_read & PR_POLL_WRITE)
                            pd->out_flags |= PR_POLL_READ;
                        if (in_flags_write & PR_POLL_WRITE)
                            pd->out_flags |= PR_POLL_WRITE;
                    }
                    if (exceptReady && (pd->in_flags & PR_POLL_EXCEPT))
                    {
                        pd->out_flags |= PR_POLL_EXCEPT;
                    }
                }
                if (0 != pd->out_flags) ready++;
            }
            else    /* bad state */
            {
                ready += 1;  /* this will cause an abrupt return */
                pd->out_flags = PR_POLL_NVAL;  /* bogii */
            }
        }
    }

    return ready;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRInt32 CheckPollDescMethods ( PRPollDesc pds,
PRIntn  npds,
PRInt16 outReadFlags,
PRInt16 outWriteFlags 
) [static]

Definition at line 1769 of file macsockotpt.c.

{
    PRInt32     ready = 0;
    PRPollDesc  *pd, *epd;
    PRInt16     *readFlag, *writeFlag;
    
    for (pd = pds, epd = pd + npds, readFlag = outReadFlags, writeFlag = outWriteFlags;
        pd < epd;
        pd++, readFlag++, writeFlag++)
    {
        PRInt16  in_flags_read = 0,  in_flags_write = 0;
        PRInt16 out_flags_read = 0, out_flags_write = 0;

        pd->out_flags = 0;

        if (NULL == pd->fd || pd->in_flags == 0) continue;

        if (pd->in_flags & PR_POLL_READ)
        {
            in_flags_read = (pd->fd->methods->poll)(
                pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
        }

        if (pd->in_flags & PR_POLL_WRITE)
        {
            in_flags_write = (pd->fd->methods->poll)(
                pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
        }

        if ((0 != (in_flags_read & out_flags_read)) ||
            (0 != (in_flags_write & out_flags_write)))
        {
            ready += 1;  /* some layer has buffer input */
            pd->out_flags = out_flags_read | out_flags_write;
        }
        
        *readFlag = in_flags_read;
        *writeFlag = in_flags_write;
    }

    return ready;
}

Here is the caller graph for this function:

static PRInt32 CountReadyPollDescs ( PRPollDesc pds,
PRIntn  npds 
) [static]

Definition at line 1878 of file macsockotpt.c.

{
    PRInt32 ready = 0;
    PRPollDesc *pd, *epd;
    
    for (pd = pds, epd = pd + npds; pd < epd; pd++)
    {
        if (pd->out_flags)
            ready ++;
    }

    return ready;
}

Here is the caller graph for this function:

static OSErr CreateSocket ( int  type,
EndpointRef *  endpoint 
) [static]

Definition at line 489 of file macsockotpt.c.

{
    OSStatus err;
    PRThread *me = _PR_MD_CURRENT_THREAD();
    char *  configName;
    OTConfiguration *config;
    EndpointRef ep;

    // for now we just create the endpoint
    // we'll make it asynchronous and give it a notifier routine in _MD_makenonblock()

    switch (type){
        case SOCK_STREAM:   configName = kTCPName;  break;
        case SOCK_DGRAM:    configName = kUDPName;  break;
    }
    config = OTCreateConfiguration(configName);
    ep = OT_OPEN_ENDPOINT(config, 0, NULL, &err);
    if (err != kOTNoError)
        goto ErrorExit;

    *endpoint = ep;
    PR_ASSERT(*endpoint != NULL);

    return kOTNoError;

ErrorExit:
    return err;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static pascal void DNSNotifierRoutine ( void contextPtr,
OTEventCode  code,
OTResult  result,
void cookie 
) [static]

Definition at line 166 of file macsockotpt.c.

{
#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();
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 353 of file macthr.c.

{
    intn is;

    PR_ASSERT(thread->md.asyncIOLock->owner == NULL);

       // DoneWaitingOnThisThread() is called from OT notifiers and async file I/O
       // callbacks that can run at "interrupt" time (Classic Mac OS) or on pthreads
       // that may run concurrently with the main threads (Mac OS X). They can thus
       // be called when any NSPR thread is running, or even while NSPR is in a
       // thread context switch. It is therefore vital that we can guarantee to
       // be able to get the asyncIOLock without blocking (thus avoiding code
       // that makes assumptions about the current NSPR thread etc). To achieve
       // this, we use NSPR interrrupts as a semaphore on the lock; all code 
       // that grabs the lock also disables interrupts for the time the lock
       // is held. Callers of DoneWaitingOnThisThread() thus have to check whether
       // interrupts are already off, and, if so, simply set the missed_IO flag on
       // the CPU rather than calling this function.
       
       _PR_INTSOFF(is);
       PR_Lock(thread->md.asyncIOLock);
       thread->io_pending = PR_FALSE;
       /* let the waiting thread know that async IO completed */
       PR_NotifyCondVar(thread->md.asyncIOCVar);
       PR_Unlock(thread->md.asyncIOLock);
       _PR_FAST_INTSON(is);
}

Here is the call graph for this function:

static PRBool GetState ( PRFileDesc fd,
PRBool readReady,
PRBool writeReady,
PRBool exceptReady 
) [static]

Definition at line 1724 of file macsockotpt.c.

{
    OTResult resultOT;
    // hack to emulate BSD sockets; say that a socket that has disconnected
    // is still readable.
    size_t   availableData = 1;
    if (!fd->secret->md.orderlyDisconnect)
        OTCountDataBytes((EndpointRef)fd->secret->md.osfd, &availableData);

    *readReady = fd->secret->md.readReady && (availableData > 0);
    *exceptReady = fd->secret->md.exceptReady;

    resultOT = OTGetEndpointState((EndpointRef)fd->secret->md.osfd);
    switch (resultOT) {
        case T_IDLE:
        case T_UNBND:
            // the socket is not connected. Emulating BSD sockets,
            // we mark it readable and writable. The next PR_Read
            // or PR_Write will then fail. Usually, in this situation,
            // fd->secret->md.exceptReady is also set, and returned if
            // anyone is polling for it.
            *readReady = PR_FALSE;
            *writeReady = PR_FALSE;
            break;

        case T_DATAXFER:        // data transfer
            *writeReady = fd->secret->md.writeReady;
            break;

        case T_INREL:           // incoming orderly release
            *writeReady = fd->secret->md.writeReady;
            break;

        case T_OUTCON:          // outgoing connection pending  
        case T_INCON:           // incoming connection pending
        case T_OUTREL:          // outgoing orderly release
        default:
            *writeReady = PR_FALSE;
    }
    
    return  *readReady || *writeReady || *exceptReady;
}

Here is the caller graph for this function:

static void macsock_map_error ( OSStatus  err) [static]

Definition at line 211 of file macsockotpt.c.

{
    _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;
        }
    }
}

Here is the caller graph for this function:

static pascal void NotifierRoutine ( void contextPtr,
OTEventCode  code,
OTResult  result,
void cookie 
) [static]

Definition at line 318 of file macsockotpt.c.

{
    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");
            return;

        case T_PASSCON:  // State is now T_DATAXFER
            // OTAccept() complete, receiving endpoint in T_DATAXFER state
            // cookie = OTAccept() resRef parameter
            break;

        case T_RESET:    // Protocol has been reset
            PR_ASSERT(!"T_RESET Not implemented");
            return;
            
// Async Completion Events
        case T_BINDCOMPLETE:
        case T_UNBINDCOMPLETE:
        case T_ACCEPTCOMPLETE:
        case T_OPTMGMTCOMPLETE:
        case T_GETPROTADDRCOMPLETE:
            readThread = secret->md.misc.thread;
            secret->md.misc.thread    = NULL;
            secret->md.misc.cookie    = cookie;
            break;

//      case T_OPENCOMPLETE:            // we open endpoints in synchronous mode
//      case T_REPLYCOMPLETE:
//      case T_DISCONNECTCOMPLETE:      // we don't call OTSndDisconnect()
//      case T_RESOLVEADDRCOMPLETE:
//      case T_GETINFOCOMPLETE:
//      case T_SYNCCOMPLETE:
//      case T_MEMORYRELEASED:          // only if OTAckSends() called on endpoint
//      case T_REGNAMECOMPLETE:
//      case T_DELNAMECOMPLETE:
//      case T_LKUPNAMECOMPLETE:
//      case T_LKUPNAMERESULT:
        // OpenTptInternet.h
//      case T_DNRSTRINGTOADDRCOMPLETE: // DNS is handled by dnsContext in DNSNotifierRoutine()
//      case T_DNRADDRTONAMECOMPLETE:
//      case T_DNRSYSINFOCOMPLETE:
//      case T_DNRMAILEXCHANGECOMPLETE:
//      case T_DNRQUERYCOMPLETE:
        default:
            // we should probably have a bit more sophisticated handling of kOTSystemSleep, etc.
            // PR_ASSERT(code != 0);
            return;
    }

    if (readThread)
        WakeUpNotifiedThread(readThread, result);

    if (writeThread && (writeThread != readThread))
        WakeUpNotifiedThread(writeThread, result);
}

Here is the call graph for this function:

Here is the caller graph for this function:

PR_IMPLEMENT ( PRInt32  long)

Definition at line 2075 of file macsockotpt.c.

{
#pragma unused (fd, how)

/* Just succeed silently!!! */
return (0);
}
PR_IMPLEMENT ( struct hostent )

Definition at line 2155 of file macsockotpt.c.

{
    OSStatus err;
    PRUint32 index;
    PRThread *me = _PR_MD_CURRENT_THREAD();

       _MD_FinishInitNetAccess();

    me->io_pending       = PR_TRUE;
    me->io_fd            = NULL;
    me->md.osErrCode     = noErr;
       
       PR_Lock(dnsContext.lock);   // so we can safely store our thread ptr in dnsContext
       dnsContext.thread = me;            // so we know what thread to wake up when OTInetStringToAddress completes

    err = OTInetStringToAddress(dnsContext.serviceRef, (char *)name, &sHostInfo);
    if (err != kOTNoError) {
        me->io_pending = PR_FALSE;
        me->md.osErrCode = err;
        goto ErrorExit;
    }

    WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
       PR_Unlock(dnsContext.lock);

    if (me->md.osErrCode != kOTNoError)
        goto ErrorExit;

    sHostEnt.h_name = sHostInfo.name;
    for (index=0; index<kMaxHostAddrs && sHostInfo.addrs[index] != NULL; index++)
        sAddresses[index] = &sHostInfo.addrs[index];
    sAddresses[index] = NULL;    
    sHostEnt.h_addr_list = (char **)sAddresses;

    return (&sHostEnt);

ErrorExit:
    return NULL;
}

Here is the call graph for this function:

PR_IMPLEMENT ( char *  )

Definition at line 2209 of file macsockotpt.c.

{
    _MD_FinishInitNetAccess();

    OTInetHostToString((InetHost)addr.s_addr, sHostInfo.name);
    
    return sHostInfo.name;
}

Here is the call graph for this function:

PR_IMPLEMENT ( struct protoent )

Definition at line 2259 of file macsockotpt.c.

{
    if (strcmp(name, kIPName) == 0)
        return (&sIPProto);
        
    if (strcmp(name, kTCPName) == 0)
        return (&sTCPProto);
        
    if (strcmp(name, kUDPName) == 0)
        return (&sUDPProto);
        
ErrorExit:
    macsock_map_error(kEINVALErr);
    return NULL;
}

Here is the call graph for this function:

static void PrepareForAsyncCompletion ( PRThread thread,
PRInt32  osfd 
) [static]

Definition at line 287 of file macsockotpt.c.

{
    thread->io_pending       = PR_TRUE;
    thread->io_fd            = osfd;
    thread->md.osErrCode     = noErr;
}

Here is the caller graph for this function:

static pascal void RawEndpointNotifierRoutine ( void contextPtr,
OTEventCode  code,
OTResult  result,
void cookie 
) [static]

Definition at line 1091 of file macsockotpt.c.

{
    RawEndpointAndThread *endthr = (RawEndpointAndThread *) contextPtr;
    PRThread *    thread   = endthr->thread;
    EndpointRef * endpoint = endthr->endpoint;
    _PRCPU *      cpu      = _PR_MD_CURRENT_CPU(); 
    OSStatus      err;
    OTResult    resultOT;

    switch (code)
    {
// OTLook Events - 
        case T_LISTEN:        // A connection request is available
            PR_ASSERT(!"T_EXDATA not implemented for raw endpoints");
            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
            break;

        case T_DATA:        // Standard data is available
                     break;

        case T_EXDATA:      // Expedited data is available
            PR_ASSERT(!"T_EXDATA Not implemented for raw endpoints");
                     return;

        case T_DISCONNECT:  // A disconnect is available
            err = OTRcvDisconnect(endpoint, NULL);
            PR_ASSERT(err == kOTNoError);
            break;
              
        case T_ERROR:       // obsolete/unused in library
            PR_ASSERT(!"T_ERROR Not implemented for raw endpoints");
                     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);
            break;          

        case T_GODATA:   // Flow control lifted on standard data
                     resultOT = OTLook(endpoint);              // clear T_GODATA event
                     PR_ASSERT(resultOT == T_GODATA);
                     
                     // wake up waiting thread, if any
            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");
            return;

        case T_PASSCON:  // State is now T_DATAXFER
                     // OTAccept() complete, receiving endpoint in T_DATAXFER state
                     // cookie = OTAccept() resRef parameter
                     break;
            
// Async Completion Events
        case T_BINDCOMPLETE:
        case T_UNBINDCOMPLETE:
        case T_ACCEPTCOMPLETE:
        case T_OPTMGMTCOMPLETE:
        case T_GETPROTADDRCOMPLETE:
            break;

              // for other OT events, see NotifierRoutine above
        default:
            return;
    }

       if (thread) {
              thread->md.osErrCode = result;
              if (_PR_MD_GET_INTSOFF()) {
                     thread->md.asyncNotifyPending = PR_TRUE;
                     cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
              } else {
                     DoneWaitingOnThisThread(thread);
              }
       }

       SignalIdleSemaphore();
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRInt32 SendReceiveDgram ( PRFileDesc fd,
void buf,
PRInt32  amount,
PRIntn  flags,
PRNetAddr addr,
PRUint32 addrlen,
PRIntervalTime  timeout,
SndRcvOpCode  opCode 
) [static]

Definition at line 1589 of file macsockotpt.c.

{
    OSStatus err;
    EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
    PRThread *me = _PR_MD_CURRENT_THREAD();
    PRInt32 bytesLeft = amount;
    TUnitData dgram;

    PR_ASSERT(flags == 0);
    
    if (endpoint == NULL) {
        err = kEBADFErr;
        goto ErrorExit;
    }
        
    if (buf == NULL || addr == NULL) {
        err = kEFAULTErr;
        goto ErrorExit;
    }
    
    if (opCode != kDGRAM_SEND && opCode != kDGRAM_RECEIVE) {
        err = kEINVALErr;
        goto ErrorExit;
    }
        
    memset(&dgram, 0 , sizeof(dgram));
    dgram.addr.maxlen = *addrlen;
    dgram.addr.len = *addrlen;
    dgram.addr.buf = (UInt8*) addr;
    dgram.udata.maxlen = amount;
    dgram.udata.len = amount;
    dgram.udata.buf = (UInt8*) buf;    

    while (bytesLeft > 0) {
    
        PrepareForAsyncCompletion(me, fd->secret->md.osfd);    

        if (opCode == kDGRAM_SEND) {
                     fd->secret->md.write.thread = me;
                     fd->secret->md.writeReady = PR_FALSE;                          // expect the worst
            err = OTSndUData(endpoint, &dgram);
                     if (err != kOTFlowErr)                                                // hope for the best
                            fd->secret->md.writeReady = PR_TRUE;
              } else {
                     fd->secret->md.read.thread = me;
                     fd->secret->md.readReady = PR_FALSE;                           // expect the worst                
            err = OTRcvUData(endpoint, &dgram, NULL);
                     if (err != kOTNoDataErr)                                              // hope for the best
                            fd->secret->md.readReady = PR_TRUE;
              }

        if (err == kOTNoError) {
            buf = (void *) ( (UInt32) buf + (UInt32)dgram.udata.len );
            bytesLeft -= dgram.udata.len;
            dgram.udata.buf = (UInt8*) buf;    
            me->io_pending = PR_FALSE;
        } else {
            PR_ASSERT(err == kOTNoDataErr || err == kOTOutStateErr);
            WaitOnThisThread(me, timeout);
            err = me->md.osErrCode;
            if (err != kOTNoError)
                goto ErrorExit;
        }
    }

    if (opCode == kDGRAM_RECEIVE)
        *addrlen = dgram.addr.len;

    return amount;

ErrorExit:
    macsock_map_error(err);
    return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRInt32 SendReceiveStream ( PRFileDesc fd,
void buf,
PRInt32  amount,
PRIntn  flags,
PRIntervalTime  timeout,
SndRcvOpCode  opCode 
) [static]

Definition at line 1397 of file macsockotpt.c.

{
    OSStatus err;
    OTResult result;
    EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
    PRThread *me = _PR_MD_CURRENT_THREAD();
    PRInt32 bytesLeft = amount;

    PR_ASSERT(flags == 0 ||
        (opCode == kSTREAM_RECEIVE && flags == PR_MSG_PEEK));
    PR_ASSERT(opCode == kSTREAM_SEND || opCode == kSTREAM_RECEIVE);
    
    if (endpoint == NULL) {
        err = kEBADFErr;
        goto ErrorExit;
    }
        
    if (buf == NULL) {
        err = kEFAULTErr;
        goto ErrorExit;
    }

    PR_ASSERT(opCode == kSTREAM_SEND ? fd->secret->md.write.thread == NULL :
                                       fd->secret->md.read.thread  == NULL);

    while (bytesLeft > 0)
    {
        Boolean disabledNotifications = OTEnterNotifier(endpoint);
    
        PrepareForAsyncCompletion(me, fd->secret->md.osfd);    

        if (opCode == kSTREAM_SEND) {
              do {
                            fd->secret->md.write.thread = me;
                            fd->secret->md.writeReady = PR_FALSE;                          // expect the worst
                   result = OTSnd(endpoint, buf, bytesLeft, NULL);
                            fd->secret->md.writeReady = (result != kOTFlowErr);
                            if (fd->secret->nonblocking)                                                 // hope for the best
                                   break;
                            else {

                                   // We drop through on anything other than a blocking write.
                                   if (result != kOTFlowErr)
                                          break;

                                   // Blocking write, but the pipe is full. Turn notifications on and
                                   // wait for an event, hoping that it's a T_GODATA event.
                    if (disabledNotifications) {
                        OTLeaveNotifier(endpoint);
                        disabledNotifications = false;
                    }
                                   WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
                                   result = me->md.osErrCode;
                                   if (result != kOTNoError) // got interrupted, or some other error
                                          break;

                                   // Prepare to loop back and try again
                                   disabledNotifications = OTEnterNotifier(endpoint);
                                   PrepareForAsyncCompletion(me, fd->secret->md.osfd);  
                            }
                     }
                     while(1);
        } else {
              do {
                            fd->secret->md.read.thread = me;
                            fd->secret->md.readReady = PR_FALSE;                           // expect the worst                
                   result = OTRcv(endpoint, buf, bytesLeft, NULL);
                   if (fd->secret->nonblocking) {
                                   fd->secret->md.readReady = (result != kOTNoDataErr);
                                   break;
                            } else {
                                   if (result != kOTNoDataErr) {
                                   // If we successfully read a blocking socket, check for more data.
                                   // According to IM:OT, we should be able to rely on OTCountDataBytes
                                   // to tell us whether there is a nonzero amount of data pending.
                                   size_t count;
                                   OSErr tmpResult;
                                   tmpResult = OTCountDataBytes(endpoint, &count);
                                    fd->secret->md.readReady = ((tmpResult == kOTNoError) && (count > 0));
                                          break;
                                }

                                   // Blocking read, but no data available. Turn notifications on and
                                   // wait for an event on this endpoint, and hope that we get a T_DATA event.
                    if (disabledNotifications) {
                        OTLeaveNotifier(endpoint);
                        disabledNotifications = false;
                    }
                                   WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
                                   result = me->md.osErrCode;
                                   if (result != kOTNoError) // interrupted thread, etc.
                                          break;

                                   // Prepare to loop back and try again
                                   disabledNotifications = OTEnterNotifier(endpoint);
                                   PrepareForAsyncCompletion(me, fd->secret->md.osfd);  
                            }
                     }
                     // Retry read if we had to wait for data to show up.
                     while(1);
        }

              me->io_pending = PR_FALSE;
              
        if (opCode == kSTREAM_SEND)
            fd->secret->md.write.thread = NULL;
        else
            fd->secret->md.read.thread  = NULL;

        // turn notifications back on
        if (disabledNotifications)
            OTLeaveNotifier(endpoint);

        if (result > 0) {
            buf = (void *) ( (UInt32) buf + (UInt32)result );
            bytesLeft -= result;
            if (opCode == kSTREAM_RECEIVE) {
                amount = result;
                goto NormalExit;
            }
        } else {
                     switch (result) {
                            case kOTLookErr:
                                PR_ASSERT(!"call to OTLook() required after all.");
                                   break;
                            
                            case kOTFlowErr:
                            case kOTNoDataErr:
                            case kEAGAINErr:
                            case kEWOULDBLOCKErr:
                                   if (fd->secret->nonblocking) {
                                   
                                       if (bytesLeft == amount) {  // no data was sent
                                              err = result;
                                              goto ErrorExit;
                                          }
                                          
                                          // some data was sent
                                          amount -= bytesLeft;
                                          goto NormalExit;
                                   }

                                   WaitOnThisThread(me, timeout);
                                   err = me->md.osErrCode;
                                   if (err != kOTNoError)
                                          goto ErrorExit;                           
                                   break;
                                   
                            case kOTOutStateErr: // if provider already closed, fall through to handle error
                                   if (fd->secret->md.orderlyDisconnect) {
                                          amount = 0;
                                          goto NormalExit;
                                   }
                                   // else fall through
                            default:
                                   err = result;
                                   goto ErrorExit;
                     }
              }
    }

NormalExit:
    PR_ASSERT(opCode == kSTREAM_SEND ? fd->secret->md.write.thread == NULL :
                                       fd->secret->md.read.thread  == NULL);
    return amount;

ErrorExit:
    PR_ASSERT(opCode == kSTREAM_SEND ? fd->secret->md.write.thread == NULL :
                                       fd->secret->md.read.thread  == NULL);
    macsock_map_error(err);
    return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void SetDescPollThread ( PRPollDesc pds,
PRIntn  npds,
PRThread thread 
) [static]

Definition at line 1893 of file macsockotpt.c.

{
    PRInt32     ready = 0;
    PRPollDesc *pd, *epd;

    for (pd = pds, epd = pd + npds; pd < epd; pd++)
    {   
        if (pd->fd)
        { 
            PRFileDesc *bottomFD = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
            if (bottomFD && (_PR_FILEDESC_OPEN == bottomFD->secret->state))
            {
                if (pd->in_flags & PR_POLL_READ) {
                    PR_ASSERT(thread == NULL || bottomFD->secret->md.read.thread == NULL);
                    bottomFD->secret->md.read.thread = thread;
                }

                if (pd->in_flags & PR_POLL_WRITE) {
                    // it's possible for the writing thread to be non-null during
                    // a non-blocking connect, so we assert that we're on
                    // the same thread, or the thread is null.
                    // Note that it's strictly possible for the connect and poll
                    // to be on different threads, so ideally we need to assert
                    // that if md.write.thread is non-null, there is a non-blocking
                    // connect in progress.
                    PR_ASSERT(thread == NULL ||
                        (bottomFD->secret->md.write.thread == NULL ||
                         bottomFD->secret->md.write.thread == thread));
                    bottomFD->secret->md.write.thread = thread;
                }
            }
        }
    }
}

Here is the caller graph for this function:

void WaitOnThisThread ( PRThread thread,
PRIntervalTime  timeout 
)

Definition at line 320 of file macthr.c.

{
    intn is;
    PRIntervalTime timein = PR_IntervalNow();
       PRStatus status = PR_SUCCESS;

    // Turn interrupts off to avoid a race over lock ownership with the callback
    // (which can fire at any time). Interrupts may stay off until we leave
    // this function, or another NSPR thread turns them back on. They certainly
    // stay off until PR_WaitCondVar() relinquishes the asyncIOLock lock, which
    // is what we care about.
       _PR_INTSOFF(is);
       PR_Lock(thread->md.asyncIOLock);
       if (timeout == PR_INTERVAL_NO_TIMEOUT) {
           while ((thread->io_pending) && (status == PR_SUCCESS))
               status = PR_WaitCondVar(thread->md.asyncIOCVar, PR_INTERVAL_NO_TIMEOUT);
       } else {
           while ((thread->io_pending) && ((PRIntervalTime)(PR_IntervalNow() - timein) < timeout) && (status == PR_SUCCESS))
               status = PR_WaitCondVar(thread->md.asyncIOCVar, timeout);
       }
       if ((status == PR_FAILURE) && (PR_GetError() == PR_PENDING_INTERRUPT_ERROR)) {
              thread->md.osErrCode = kEINTRErr;
       } else if (thread->io_pending) {
              thread->md.osErrCode = kETIMEDOUTErr;
              PR_SetError(PR_IO_TIMEOUT_ERROR, kETIMEDOUTErr);
       }

       thread->io_pending = PR_FALSE;
       PR_Unlock(thread->md.asyncIOLock);
       _PR_FAST_INTSON(is);
}

Here is the call graph for this function:

void WakeUpNotifiedThread ( PRThread thread,
OTResult  result 
)

Definition at line 296 of file macsockotpt.c.

{
    _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();
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

struct { ... } dnsContext [static]
OTNotifyUPP DNSNotifierRoutineUPP [static]

Definition at line 101 of file macsockotpt.c.

struct hostent = {NULL, &sAliases[0], AF_INET, sizeof (long), NULL} [static]

Definition at line 2150 of file macsockotpt.c.

OTNotifyUPP NotifierRoutineUPP [static]

Definition at line 102 of file macsockotpt.c.

static struct protoent = {kIPName, NULL, INET_IP} [static]

Definition at line 2255 of file macsockotpt.c.

OTNotifyUPP RawEndpointNotifierRoutineUPP [static]

Definition at line 103 of file macsockotpt.c.

InetHost* sAddresses[kMaxHostAddrs+1] [static]

Definition at line 2152 of file macsockotpt.c.

char* sAliases[1] = {NULL} [static]

Definition at line 2149 of file macsockotpt.c.

InetHostInfo sHostInfo [static]

Definition at line 2151 of file macsockotpt.c.