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

📄 gsocket.c

📁 Wxpython Implemented on Windows CE, Source code
💻 C
📖 第 1 页 / 共 3 页
字号:
/* -------------------------------------------------------------------------
 * Project: GSocket (Generic Socket) for WX
 * Name:    src/mac/classic/gsocket.c
 * Authors: Guilhem Lavaux,
 *          Guillermo Rodriguez Garcia <guille@iies.es> (maintainer)
 *          Stefan CSomor
 * Purpose: GSocket main mac file
 * CVSID:   $Id: gsocket.c,v 1.4 2006/01/26 19:53:01 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>

  #ifndef FALSE
    #define FALSE 0
  #endif
  #ifndef TRUE
    #define TRUE 1
  #endif
#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__ */

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 )
	{
		YieldToAnyThread() ;
		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(struct GSocketGUIFunctionsTable *table)
{
    // do nothing, wxMac doesn't have wxBase-GUI separation yet
}

int GSocket_Init()
{
    return TRUE;
}

int GSocket_Verify_Inited() ;
int 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_new()
{

  int i;
  GSocket *socket;

 if ( GSocket_Verify_Inited() == FALSE )
    return NULL ;

  socket = (GSocket *)malloc(sizeof(GSocket));

  if (socket == NULL)
    return NULL;

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

void GSocket_destroy(GSocket *socket)
{
  assert(socket != NULL);

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


  /* Destroy private addresses */
  if (socket->m_local)
    GAddress_destroy(socket->m_local);

  if (socket->m_peer)
    GAddress_destroy(socket->m_peer);

  /* Destroy the socket itself */
  free(socket);
}

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

  assert(socket != NULL);

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

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

  socket->m_detected = 0;
  _GSocket_Disable_Events(socket);
  wxMacRemoveAllNotifiersForData( wxMacGetNotifierTable() , socket ) ;
}


/* 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(GSocket *socket, GAddress *address)
{
  assert(socket != NULL);

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

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

  if (socket->m_local)
    GAddress_destroy(socket->m_local);

  socket->m_local = GAddress_copy(address);

  return GSOCK_NOERROR;
}

GSocketError GSocket_SetPeer(GSocket *socket, GAddress *address)
{
  assert(socket != NULL);

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

  if (socket->m_peer)
    GAddress_destroy(socket->m_peer);

  socket->m_peer = GAddress_copy(address);

  return GSOCK_NOERROR;
}

GAddress *GSocket_GetLocal(GSocket *socket)
{
  GAddress *address = NULL ;
  GSocketError err;
  InetAddress loc ;

  assert(socket != NULL);

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

  /* else, if the socket is initialized, try getsockname */
  if (socket->m_endpoint == kOTInvalidEndpointRef)
  {
    socket->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)
  {
    socket->m_error = GSOCK_MEMERR;
    return NULL;
  }

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

  return address;
}

GAddress *GSocket_GetPeer(GSocket *socket)
{
  assert(socket != NULL);

  /* try to get it from the m_peer var */
  if (socket->m_peer)
    return GAddress_copy(socket->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(GSocket *sck)
{
  assert(sck != NULL);

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

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

  /* Initialize all fields */
  sck->m_stream   = TRUE;
  sck->m_server   = TRUE;
  sck->m_oriented = TRUE;

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

  ioctl(sck->m_endpoint, FIONBIO, &arg);
  _GSocket_Enable_Events(sck);

  /* Bind to the local address,
   * retrieve the actual address bound,
   * and listen up to 5 connections.
   */
  if ((bind(sck->m_endpoint, sck->m_local->m_addr, sck->m_local->m_len) != 0) ||
      (getsockname(sck->m_endpoint,
                   sck->m_local->m_addr,
                   (WX_SOCKLEN_T *) &sck->m_local->m_len) != 0) ||
      (listen(sck->m_endpoint, 5) != 0))
  {
    close(sck->m_endpoint);
    sck->m_endpoint = -1;
    sck->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 *socket)
{

⌨️ 快捷键说明

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