📄 gsocket.c
字号:
/* ------------------------------------------------------------------------- * 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 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 ) { 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 + -