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

📄 gsocket.cpp

📁 Wxpython Implemented on Windows CE, Source code
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* -------------------------------------------------------------------------
 * Project:     GSocket (Generic Socket) for WX
 * Name:        src/mac/carbon/gsocket.cpp
 * Copyright:   (c) Guilhem Lavaux
 * Licence:     wxWindows Licence
 * Authors:     Guilhem Lavaux,
 *              Guillermo Rodriguez Garcia <guille@iies.es> (maintainer)
 *              Stefan CSomor
 * Purpose:     GSocket main mac file
 * CVSID:       $Id: gsocket.cpp,v 1.12 2006/01/26 19:52:58 ABX Exp $
 * -------------------------------------------------------------------------
 */

/*
 * PLEASE don't put C++ comments here - this is a C source file.
 */

#ifndef __GSOCKET_STANDALONE__
#include "wx/platform.h"
#endif

#if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__)

#ifdef __DARWIN__
    #include <CoreServices/CoreServices.h>
#else
    #include <MacHeaders.c>
    #define OTUNIXERRORS 1
    #include <OpenTransport.h>
    #include <OpenTransportProviders.h>
    #include <OpenTptInternet.h>
#endif
#if TARGET_CARBON && !defined(OTAssert)
    #define OTAssert( str , cond ) /* does not exists in Carbon */
#endif

#include <assert.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <ctype.h>
#include <utime.h>

/*
 * INADDR_BROADCAST is identical to INADDR_NONE which is not defined
 * on all unices. INADDR_BROADCAST should be fine to indicate an error.
 */
#ifndef INADDR_BROADCAST
#define INADDR_BROADCAST 0xFFFFFFFFUL
#endif
#ifndef INADDR_NONE
#define INADDR_NONE INADDR_BROADCAST
#endif
#ifndef INADDR_ANY
#define INADDR_ANY 0x0UL
#endif
#ifndef __GSOCKET_STANDALONE__

    #include "wx/mac/macnotfy.h"
    #include "wx/mac/gsockmac.h"
    #include "wx/gsocket.h"

#else

    #include "gsockmac.h"
    #include "gsocket.h"

#endif /* __GSOCKET_STANDALONE__ */

#ifndef ntohl
    #define  ntohl(x) (x)
    #define  ntohs(x) (x)
    #define  htonl(x) (x)
    #define  htons(x) (x)
#endif

void wxCYield() ;
#ifdef __WXDEBUG__
#define qDebug 1
#define qDebug2 1
extern pascal void OTDebugStr(const char* str);
#endif
#ifndef __DARWIN__
  #include <OTDebug.h>
#endif
InetSvcRef gInetSvcRef = 0 ;
int gOTInited = 0 ;
OTNotifyUPP gOTNotifierUPP = NULL ;

OSStatus DoNegotiateIPReuseAddrOption(EndpointRef ep, Boolean enableReuseIPMode);

/* Input: ep - endpointref on which to negotiate the option
               enableReuseIPMode - desired option setting - true/false
   Return: kOTNoError indicates that the option was successfully negotiated
           OSStatus is an error if < 0, otherwise, the status field is
           returned and is > 0.

   IMPORTANT NOTE: The endpoint is assumed to be in synchronous more, otherwise
                   this code will not function as desired
*/


OSStatus DoNegotiateIPReuseAddrOption(EndpointRef ep, Boolean enableReuseIPMode)

{
    UInt8        buf[kOTFourByteOptionSize]; // define buffer for fourByte Option size
    TOption*     opt;                        // option ptr to make items easier to access
    TOptMgmt     req;
    TOptMgmt     ret;
    OSStatus     err;

    if (!OTIsSynchronous(ep))
    {
        return (-1);
    }
    opt = (TOption*)buf; // set option ptr to buffer
    req.opt.buf = buf;
    req.opt.len = sizeof(buf);
    req.flags   = T_NEGOTIATE;    // negotiate for option

    ret.opt.buf = buf;
    ret.opt.maxlen = kOTFourByteOptionSize;

    opt->level  = INET_IP;        // dealing with an IP Level function
#ifdef __DARWIN__
    opt->name   = kIP_REUSEADDR;
#else
    opt->name   = IP_REUSEADDR;
#endif
    opt->len    = kOTFourByteOptionSize;
    opt->status = 0;
    *(UInt32*)opt->value = enableReuseIPMode;   // set the desired option level, true or false

    err = OTOptionManagement(ep, &req, &ret);

    // if no error then return the option status value
    if (err == kOTNoError)
    {
        if (opt->status != T_SUCCESS)
            err = opt->status;
        else
            err = kOTNoError;
    }

    return err;
}


pascal void OTInetEventHandler(void*s, OTEventCode event, OTResult, void *cookie) ;
pascal void OTInetEventHandler(void*s, OTEventCode event, OTResult result, void *cookie)
{
    int wakeUp = true ;
    GSocket* sock = (GSocket*) s ;

    if ( event == kOTSyncIdleEvent )
    {
        return ;
    }

    if ( s )
    {
        wxMacAddEvent( sock->m_mac_events , _GSocket_Internal_Proc , event , s , wakeUp ) ;
    }

    return;
}

static void SetDefaultEndpointModes(EndpointRef ep , void *data )
    // This routine sets the supplied endpoint into the default
    // mode used in this application.  The specifics are:
    // blocking, synchronous, and using synch idle events with
    // the standard YieldingNotifier.
{
    OSStatus junk = kOTNoError ;
    OTAssert ("SetDefaultEndpointModes:invalid ref", ep != kOTInvalidEndpointRef ) ;
    junk = OTSetAsynchronous(ep);
    OTAssert("SetDefaultEndpointModes: Could not set asynchronous", junk == noErr);
/*
    junk = OTSetBlocking(ep);
    OTAssert("SetDefaultEndpointModes: Could not set blocking", junk == noErr);
    junk = OTSetSynchronous(ep);
    OTAssert("SetDefaultEndpointModes: Could not set synchronous", junk == noErr);
    junk = OTSetBlocking(ep);
    OTAssert("SetDefaultEndpointModes: Could not set blocking", junk == noErr);
*/
    junk = OTInstallNotifier(ep, gOTNotifierUPP, data);
    OTAssert("SetDefaultEndpointModes: Could not install notifier", junk == noErr);
/*
    junk = OTUseSyncIdleEvents(ep, true);
    OTAssert("SetDefaultEndpointModes: Could not use sync idle events", junk == noErr);
*/
}

/* Global initialisers */

void GSocket_SetGUIFunctions(GSocketGUIFunctionsTable *table)
{
    // do nothing, wxMac doesn't have wxBase-GUI separation yet
}

int GSocket_Init()
{
    return 1;
}

bool GSocket_Verify_Inited() ;
bool GSocket_Verify_Inited()
{
    OSStatus err ;
#if TARGET_CARBON
    // Marc Newsam: added the clientcontext variable
    //              however, documentation is unclear how this works
    OTClientContextPtr clientcontext;

    if ( gInetSvcRef )
      return true ;

    InitOpenTransportInContext(kInitOTForApplicationMask, &clientcontext);
    gOTInited = 1 ;
    gInetSvcRef = OTOpenInternetServicesInContext(kDefaultInternetServicesPath,
                                                  NULL, &err, clientcontext);
#else
    if ( gInetSvcRef )
      return true ;

    InitOpenTransport() ;
    gOTInited = 1 ;
    gInetSvcRef = OTOpenInternetServices(kDefaultInternetServicesPath, NULL, &err);
#endif
    if ( gInetSvcRef == NULL ||  err != kOTNoError )
    {
        OTAssert("Could not open Inet Services", err == noErr);
        return false ;
    }
    gOTNotifierUPP = NewOTNotifyUPP( OTInetEventHandler ) ;
    return true ;
}

void GSocket_Cleanup()
{
    if ( gOTInited != 0 )
    {
        if ( gInetSvcRef != NULL )
            OTCloseProvider( gInetSvcRef );
    #if TARGET_CARBON
      CloseOpenTransportInContext( NULL ) ;
    #else
      CloseOpenTransport() ;
    #endif
        if ( gOTNotifierUPP )
            DisposeOTNotifyUPP( gOTNotifierUPP ) ;
    }
}

/* Constructors / Destructors for GSocket */

GSocket::GSocket()
{
  int i;

  m_ok = GSocket_Verify_Inited();

  m_endpoint                  = NULL ;
  for (i=0;i<GSOCK_MAX_EVENT;i++)
  {
    m_cbacks[i]         = NULL;
  }
  m_detected            = 0;
  m_local               = NULL;
  m_peer                = NULL;
  m_error               = GSOCK_NOERROR;
  m_server              = false;
  m_stream              = true;
  m_non_blocking        = false;
  m_timeout             = 1*1000;
                                /* 10 sec * 1000 millisec */
  m_takesEvents         = true ;
  m_mac_events          = wxMacGetNotifierTable() ;
}

GSocket::~GSocket()
{
    assert(this);

    /* Check that the socket is really shutdowned */
    if (m_endpoint != kOTInvalidEndpointRef)
        Shutdown();


    /* Destroy private addresses */
    if (m_local)
        GAddress_destroy(m_local);

    if (m_peer)
        GAddress_destroy(m_peer);
}

/* GSocket_Shutdown:
 *  Disallow further read/write operations on this socket, close
 *  the fd and disable all callbacks.
 */
void GSocket::Shutdown()
{
    OSStatus err ;
    int evt;

    assert(this);

    /* If socket has been created, shutdown it */
    if (m_endpoint != kOTInvalidEndpointRef )
    {
        err = OTSndOrderlyDisconnect( m_endpoint ) ;
        if ( err != kOTNoError )
        {
        }

        err = OTRcvOrderlyDisconnect( m_endpoint ) ;
        err = OTUnbind( m_endpoint ) ;
        err = OTCloseProvider( m_endpoint ) ;
        m_endpoint = kOTInvalidEndpointRef ;
    }

    /* Disable GUI callbacks */
    for (evt = 0; evt < GSOCK_MAX_EVENT; evt++)
        m_cbacks[evt] = NULL;

    m_detected = 0;
    Disable_Events();
    wxMacRemoveAllNotifiersForData( wxMacGetNotifierTable() , this ) ;
}


/* Address handling */

/* GSocket_SetLocal:
 * GSocket_GetLocal:
 * GSocket_SetPeer:
 * GSocket_GetPeer:
 *  Set or get the local or peer address for this socket. The 'set'
 *  functions return GSOCK_NOERROR on success, an error code otherwise.
 *  The 'get' functions return a pointer to a GAddress object on success,
 *  or NULL otherwise, in which case they set the error code of the
 *  corresponding GSocket.
 *
 *  Error codes:
 *    GSOCK_INVSOCK - the socket is not valid.
 *    GSOCK_INVADDR - the address is not valid.
 */
GSocketError GSocket::SetLocal(GAddress *address)
{
    assert(this);

    /* the socket must be initialized, or it must be a server */
    if ((m_endpoint != kOTInvalidEndpointRef && !m_server))
    {
        m_error = GSOCK_INVSOCK;
        return GSOCK_INVSOCK;
    }

    /* check address */
    if (address == NULL || address->m_family == GSOCK_NOFAMILY)
    {
        m_error = GSOCK_INVADDR;
        return GSOCK_INVADDR;
    }

    if (m_local)
        GAddress_destroy(m_local);

    m_local = GAddress_copy(address);

    return GSOCK_NOERROR;
}

GSocketError GSocket::SetPeer(GAddress *address)
{
    assert(this);

    /* check address */
    if (address == NULL || address->m_family == GSOCK_NOFAMILY)
    {
        m_error = GSOCK_INVADDR;
        return GSOCK_INVADDR;
    }

    if (m_peer)
        GAddress_destroy(m_peer);

    m_peer = GAddress_copy(address);

    return GSOCK_NOERROR;
}

GAddress *GSocket::GetLocal()
{
    GAddress *address = NULL ;
    GSocketError err;
    InetAddress loc ;

    assert(this);

    /* try to get it from the m_local var first */
    if (m_local)
        return GAddress_copy(m_local);

    /* else, if the socket is initialized, try getsockname */
    if (m_endpoint == kOTInvalidEndpointRef)
    {
        m_error = GSOCK_INVSOCK;
        return NULL;
    }


/* we do not support multihoming with this code at the moment
   OTGetProtAddress will have to be used then - but we don't have a handy
   method to use right now
*/
    {
        InetInterfaceInfo info;
        OTInetGetInterfaceInfo(&info, kDefaultInetInterface);
        loc.fHost = info.fAddress ;
        loc.fPort = 0 ;
        loc.fAddressType = AF_INET ;
    }

    /* got a valid address from getsockname, create a GAddress object */
    address = GAddress_new();
    if (address == NULL)
    {
        m_error = GSOCK_MEMERR;
        return NULL;
    }

    err = _GAddress_translate_from(address, &loc);
    if (err != GSOCK_NOERROR)
    {
        GAddress_destroy(address);
        m_error = err;
        return NULL;
    }

    return address;
}

GAddress *GSocket::GetPeer()
{
    assert(this);

    /* try to get it from the m_peer var */
    if (m_peer)
        return GAddress_copy(m_peer);

    return NULL;
}

/* Server specific parts */

/* GSocket_SetServer:
 *  Sets up this socket as a server. The local address must have been
 *  set with GSocket_SetLocal() before GSocket_SetServer() is called.
 *  Returns GSOCK_NOERROR on success, one of the following otherwise:
 *
 *  Error codes:
 *    GSOCK_INVSOCK - the socket is in use.
 *    GSOCK_INVADDR - the local address has not been set.
 *    GSOCK_IOERR   - low-level error.
 */
GSocketError GSocket::SetServer()
{
  assert(this);

  /* must not be in use */
  if (m_endpoint != kOTInvalidEndpointRef )
  {
    m_error = GSOCK_INVSOCK;
    return GSOCK_INVSOCK;
  }

  /* the local addr must have been set */
  if (!m_local)
  {
    m_error = GSOCK_INVADDR;
    return GSOCK_INVADDR;
  }

  /* Initialize all fields */
  m_stream   = true;
  m_server   = true;
  m_oriented = true;

// TODO
#if 0
  /* Create the socket */
  m_endpoint = socket(m_local->m_realfamily, SOCK_STREAM, 0);
  socket_set_ref( m_endpoint , (unsigned long) &gMacNetEvents ,  (unsigned long) this ) ;
  if (m_endpoint == kOTInvalidEndpointRef)
  {
    m_error = GSOCK_IOERR;
    return GSOCK_IOERR;
  }

  ioctl(m_endpoint, FIONBIO, &arg);
  Enable_Events();

  /* Bind to the local address,
   * retrieve the actual address bound,
   * and listen up to 5 connections.
   */
  if ((bind(m_endpoint, m_local->m_addr, m_local->m_len) != 0) ||
      (getsockname(m_endpoint,
                   m_local->m_addr,
                   (WX_SOCKLEN_T *) &m_local->m_len) != 0) ||
      (listen(m_endpoint, 5) != 0))
  {
    close(m_endpoint);
    m_endpoint = -1;
    m_error = GSOCK_IOERR;
    return GSOCK_IOERR;
  }
#endif
  return GSOCK_NOERROR;
}

/* GSocket_WaitConnection:
 *  Waits for an incoming client connection. Returns a pointer to
 *  a GSocket object, or NULL if there was an error, in which case
 *  the last error field will be updated for the calling GSocket.
 *
 *  Error codes (set in the calling GSocket)
 *    GSOCK_INVSOCK    - the socket is not valid or not a server.
 *    GSOCK_TIMEDOUT   - timeout, no incoming connections.
 *    GSOCK_WOULDBLOCK - the call would block and the socket is nonblocking.
 *    GSOCK_MEMERR     - couldn't allocate memory.
 *    GSOCK_IOERR      - low-level error.
 */
GSocket *GSocket::WaitConnection()
{
  GSocket *connection = NULL ;

  assert(this);

  /* Reenable CONNECTION events */
  m_detected &= ~GSOCK_CONNECTION_FLAG;

  /* If the socket has already been created, we exit immediately */
  if (m_endpoint == kOTInvalidEndpointRef || !m_server)
  {
    m_error = GSOCK_INVSOCK;

⌨️ 快捷键说明

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