📄 gsocket.cpp
字号:
/* ------------------------------------------------------------------------- * 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)#endifvoid wxCYield() ;#ifdef __WXDEBUG__#define qDebug 1#define qDebug2 1extern pascal void OTDebugStr(const char* str);#endif#ifndef __DARWIN__ #include <OTDebug.h>#endifInetSvcRef 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 + -