Exemple #1
0
void socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info) {
    CFSocketNativeHandle socket = (CFSocketNativeHandle)(*((CFSocketNativeHandle *)data));
	
    struct msghdr message;
    struct iovec iov[1];
    struct cmsghdr *control_message = NULL;
    char ctrl_buf[CMSG_SPACE(sizeof(int))];
    char dummy_data[1];
	
    memset(&message, 0, sizeof(struct msghdr));
    memset(ctrl_buf, 0, CMSG_SPACE(sizeof(int)));
	
    dummy_data[0] = ' ';
    iov[0].iov_base = dummy_data;
    iov[0].iov_len = sizeof(dummy_data);
	
    message.msg_name = NULL;
    message.msg_namelen = 0;
    message.msg_iov = iov;
    message.msg_iovlen = 1;
    message.msg_controllen = CMSG_SPACE(sizeof(int));
    message.msg_control = ctrl_buf;
	
    control_message = CMSG_FIRSTHDR(&message);
    control_message->cmsg_level = SOL_SOCKET;
    control_message->cmsg_type = SCM_RIGHTS;
    control_message->cmsg_len = CMSG_LEN(sizeof(int));
	
    *((uintptr_t *) CMSG_DATA(control_message)) = (uintptr_t)info;
	
    sendmsg(socket, &message, 0);
    CFSocketInvalidate(s);
    CFRelease(s);
}
Exemple #2
0
/*
 * CFRunloop callback that calls DNSServiceProcessResult() when
 * there's new data on the socket.
 */
static void
socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *context)
{
	struct cbinfo *info = context;
	DNSServiceErrorType err;

	if (callbackType == kCFSocketNoCallBack) {
		printf("socket_callback: kCFSocketNoCallBack?\n");
		return;
	}

	if ((err = DNSServiceProcessResult(info->sdref)) != kDNSServiceErr_NoError) {
		printf("DNSServiceProcessResult() returned an error! %d\n", err);
		if (err == kDNSServiceErr_BadReference) {
			printf("bad reference?: %p, %d, %p, %p %p\n", s, (int)callbackType, address, data, context);
			return;
		}
		if ((context == &nfsinfo) || (context == &mountdinfo)) {
			/* bail if there's a problem with the main browse connection */
			exit(1);
		}
		/* dump the troublesome service connection */
		CFRunLoopRemoveSource(CFRunLoopGetCurrent(), info->rls, kCFRunLoopDefaultMode);
		CFRelease(info->rls);
		CFSocketInvalidate(info->sockref);
		CFRelease(info->sockref);
		DNSServiceRefDeallocate(info->sdref);
		free(info);
	}
}
static void
eventCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info)
{
	int			so		= CFSocketGetNative(s);
	int			status;
	char			buf[1024];
	struct kern_event_msg	*ev_msg		= (struct kern_event_msg *)&buf[0];
	int			offset		= 0;

	status = recv(so, &buf, sizeof(buf), 0);
	if (status == -1) {
		SCLog(TRUE, LOG_ERR, CFSTR("recv() failed: %s"), strerror(errno));
		goto error;
	}

	cache_open();

	while (offset < status) {
		if ((offset + ev_msg->total_size) > status) {
			SCLog(TRUE, LOG_NOTICE, CFSTR("missed SYSPROTO_EVENT event, buffer not big enough"));
			break;
		}

		switch (ev_msg->vendor_code) {
			case KEV_VENDOR_APPLE :
				switch (ev_msg->kev_class) {
					case KEV_NETWORK_CLASS :
						processEvent_Apple_Network(ev_msg);
						break;
					case KEV_IOKIT_CLASS :
						processEvent_Apple_IOKit(ev_msg);
						break;
					default :
						/* unrecognized (Apple) event class */
						logEvent(CFSTR("New (Apple) class"), ev_msg);
						break;
				}
				break;
			default :
				/* unrecognized vendor code */
				logEvent(CFSTR("New vendor"), ev_msg);
				break;
		}
		offset += ev_msg->total_size;
		ev_msg = (struct kern_event_msg *)&buf[offset];
	}

	cache_write(store);
	cache_close();

	return;

    error :

	SCLog(TRUE, LOG_ERR, CFSTR("kernel event monitor disabled."));
	CFSocketInvalidate(s);
	return;

}
Exemple #4
0
wxCFEventLoopSource::~wxCFEventLoopSource()
{
    if ( m_cfSocket )
    {
        CFSocketInvalidate(m_cfSocket);
        CFRelease(m_cfSocket);
    }
}
/*== Remove socket ==*/
int removeSocketAtIndex(int index, transport_context_t *context)
{
	int i;
	
	tsk_safeobj_lock(context);
    
	if (index < (int)context->count) {
        transport_socket_t *sock = context->sockets[index];
        
		// Free tls context
		//TSK_OBJECT_SAFE_FREE(sock->tlshandle);
		
		// Invalidate CFSocket
        if (sock->cf_socket) {
            if (CFSocketIsValid(sock->cf_socket)) {
                CFSocketInvalidate(sock->cf_socket);
            }
            CFRelease(sock->cf_socket);
        }
		// Close and free read stream
        if (sock->cf_read_stream) {
            // TODO: Investigate if we really need to do that
            //if (CFReadStreamGetStatus(sock->cf_read_stream) == kCFStreamStatusOpen) {
            //    CFReadStreamClose(sock->cf_read_stream);
            //}
            CFRelease(sock->cf_read_stream);
        }
		// Close and free write stream
        if (sock->cf_write_stream) {
            // TODO: Investigate if we really need to do that
            //if (CFWriteStreamGetStatus(sock->cf_write_stream) == kCFStreamStatusOpen) {
            //    CFWriteStreamClose(sock->cf_write_stream);
            //}
            CFRelease(sock->cf_write_stream);
        }
        
		// Close the socket if we are the owner.
		if (sock->owner) {
			tnet_sockfd_close(&(sock->fd));
		}
        
		TSK_FREE(sock);
		
		for(i=index ; i<context->count-1; i++) {			
			context->sockets[i] = context->sockets[i+1];
		}
		
		context->sockets[context->count-1] = 0;
		context->count--;
        
		TSK_DEBUG_INFO("Socket removed");
	}
    
	tsk_safeobj_unlock(context);
	
	return 0;
}
Exemple #6
0
void GSocketGUIFunctionsTableConcrete::Disable_Events(GSocket *socket)
{
    struct MacGSocketData* data = _GSocket_Get_Mac_Socket(socket);
    if (!data) return;

    /* CFSocketInvalidate does CFRunLoopRemoveSource anyway */
    CFRunLoopRemoveSource(s_mainRunLoop, data->source, kCFRunLoopCommonModes);
    CFSocketInvalidate(data->socket);
}
Exemple #7
0
/* extern */ void
_CFTypeInvalidate(CFTypeRef obj) {

	CFTypeID t = CFGetTypeID(obj);

	/* Invalidate according to type of object. */
	if (t == CFRunLoopSourceGetTypeID()) {
		CFRunLoopSourceInvalidate((CFRunLoopSourceRef)obj);
	}

	else if (t == CFMachPortGetTypeID()) {
		CFMachPortInvalidate((CFMachPortRef)obj);
	}

	else if (t == CFSocketGetTypeID()) {
		CFSocketInvalidate((CFSocketRef)obj);
	}

	/* For scheduled types of objects, it is invalidated by setting the client to NULL. */
	else if (t == CFReadStreamGetTypeID()) {
		CFReadStreamSetClient((CFReadStreamRef)obj, kCFStreamEventNone, NULL, NULL);
	}

	else if (t == CFWriteStreamGetTypeID()) {
		CFWriteStreamSetClient((CFWriteStreamRef)obj, kCFStreamEventNone, NULL, NULL);
	}

	else if (t == CFHostGetTypeID()) {
		CFHostSetClient((CFHostRef)obj, NULL, NULL);
	}

	else if (t == SCNetworkReachabilityGetTypeID()) {
		SCNetworkReachabilitySetCallback((SCNetworkReachabilityRef)obj, NULL, NULL);
	}

	else if (t == CFRunLoopTimerGetTypeID()) {
		CFRunLoopTimerInvalidate((CFRunLoopTimerRef)obj);
	}

	else if (t == CFNetServiceGetTypeID()) {
		CFNetServiceSetClient((CFNetServiceRef)obj, NULL, NULL);
	}

	else if (t == CFNetServiceBrowserGetTypeID()) {
		CFNetServiceBrowserInvalidate((CFNetServiceBrowserRef)obj);
	}

	else if (t == CFNetServiceMonitorGetTypeID()) {
		CFNetServiceMonitorInvalidate((CFNetServiceMonitorRef)obj);
	}

	else if (t == SCNetworkReachabilityGetTypeID()) {
		SCNetworkConnectionStop((SCNetworkConnectionRef)obj, FALSE);
	}
}
Exemple #8
0
/*!
    Called due to source signal detected by the CFRunLoop.
    This is nearly identical to the wxGTK equivalent.
 */
extern "C" void WXCF_EndProcessDetector(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, void const *data, void *info)
{
    wxEndProcessData * const proc_data = static_cast<wxEndProcessData*>(info);

/// This code could reasonably be shared between wxMac/wxCocoa and wxGTK ///
    // PID is always positive on UNIX but wx uses the sign bit as a flag.
    int pid = (proc_data->pid > 0) ? proc_data->pid : -proc_data->pid;
    int status = 0;
    int rc = waitpid(pid, &status, WNOHANG);
    if(rc == 0)
    {
        // Keep waiting in case we got a spurious notification
        // NOTE: In my limited testing, this doesn't happen.
        return;
    }

    if(rc == -1)
    {   // Error.. really shouldn't happen but try to gracefully handle it
        wxLogLastError(_T("waitpid"));
        proc_data->exitcode = -1;
    }
    else
    {   // Process ended for some reason
        wxASSERT_MSG(rc == pid, _T("unexpected waitpid() return value"));

        if(WIFEXITED(status))
            proc_data->exitcode = WEXITSTATUS(status);
        else if(WIFSIGNALED(status))
            // wxGTK doesn't do this but why not?
            proc_data->exitcode = -WTERMSIG(status);
        else
        {   // Should NEVER happen according to waitpid docs
            wxLogError(wxT("waitpid indicates process exited but not due to exiting or signalling"));
            proc_data->exitcode = -1;
        }
    }
/// The above code could reasonably be shared between wxMac/wxCocoa and wxGTK ///

    /*
        Either waitpid failed or the process ended successfully.  Either way,
        we're done.  It's not if waitpid is going to magically succeed when
        we get fired again.  CFSocketInvalidate closes the fd for us and also
        invalidates the run loop source for us which should cause it to
        release the CFSocket (thus causing it to be deallocated) and remove
        itself from the runloop which should release it and cause it to also
        be deallocated.  Of course, it's possible the RunLoop hangs onto
        one or both of them by retaining/releasing them within its stack
        frame.  However, that shouldn't be depended on.  Assume that s is
        deallocated due to the following call.
     */
    CFSocketInvalidate(s);

    // Now tell wx that the process has ended.
    wxHandleProcessTermination(proc_data);
}
Exemple #9
0
int
browse(void)
{
	DNSServiceErrorType err;
	CFSocketContext ctx = { 0, NULL, NULL, NULL, NULL };

	err = DNSServiceBrowse(&nfsinfo.sdref, 0, 0, "_nfs._tcp", NULL, browser_callback, NULL);
	if (err != kDNSServiceErr_NoError)
		return (1);
	ctx.info = (void*)&nfsinfo;
	nfsinfo.sockref = CFSocketCreateWithNative(kCFAllocatorDefault, DNSServiceRefSockFD(nfsinfo.sdref),
			kCFSocketReadCallBack, socket_callback, &ctx);
	if (!nfsinfo.sockref)
		return (1);
	nfsinfo.rls = CFSocketCreateRunLoopSource(kCFAllocatorDefault, nfsinfo.sockref, 1);
	CFRunLoopAddSource(CFRunLoopGetCurrent(), nfsinfo.rls, kCFRunLoopDefaultMode);

	/* For backwards compatibility, browse for "mountd" services too */
	err = DNSServiceBrowse(&mountdinfo.sdref, 0, 0, "_mountd._tcp", NULL, browser_callback, NULL);
	if (err != kDNSServiceErr_NoError)
		return (1);
	ctx.info = (void*)&mountdinfo;
	mountdinfo.sockref = CFSocketCreateWithNative(kCFAllocatorDefault, DNSServiceRefSockFD(mountdinfo.sdref),
			kCFSocketReadCallBack, socket_callback, &ctx);
	if (!mountdinfo.sockref)
		return (1);
	mountdinfo.rls = CFSocketCreateRunLoopSource(kCFAllocatorDefault, mountdinfo.sockref, 1);
	CFRunLoopAddSource(CFRunLoopGetCurrent(), mountdinfo.rls, kCFRunLoopDefaultMode);

	CFRunLoopRun();

	CFRelease(nfsinfo.rls);
	CFSocketInvalidate(nfsinfo.sockref);
	CFRelease(nfsinfo.sockref);
	DNSServiceRefDeallocate(nfsinfo.sdref);
	CFRelease(mountdinfo.rls);
	CFSocketInvalidate(mountdinfo.sockref);
	CFRelease(mountdinfo.sockref);
	DNSServiceRefDeallocate(mountdinfo.sdref);
	return (0);
}
void QCFSocketNotifier::removeSocketNotifiers()
{
    // Remove CFSockets from the runloop.
    for (MacSocketHash::ConstIterator it = macSockets.constBegin(); it != macSockets.constEnd(); ++it) {
        MacSocketInfo *socketInfo = (*it);
        if (CFSocketIsValid(socketInfo->socket)) {
            qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop);
            CFRunLoopSourceInvalidate(socketInfo->runloop);
            CFRelease(socketInfo->runloop);
            CFSocketInvalidate(socketInfo->socket);
            CFRelease(socketInfo->socket);
        }
    }
}
/*
    Unregister QSocketNotifer. The CFSocket correspoding to this notifier is
    removed from the runloop of this is the last notifier that users
    that CFSocket.
*/
void QEventDispatcherMac::unregisterSocketNotifier(QSocketNotifier *notifier)
{
    Q_ASSERT(notifier);
    int nativeSocket = notifier->socket();
    int type = notifier->type();
#ifndef QT_NO_DEBUG
    if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) {
        qWarning("QSocketNotifier: Internal error");
        return;
    } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
        qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread");
        return;
    }
#endif

    Q_D(QEventDispatcherMac);
    QEventDispatcherUNIX::unregisterSocketNotifier(notifier);

    if (type == QSocketNotifier::Exception) {
        qWarning("QSocketNotifier::Exception is not supported on Mac OS X");
        return;
    }
    MacSocketInfo *socketInfo = d->macSockets.value(nativeSocket);
    if (!socketInfo) {
        qWarning("QEventDispatcherMac::unregisterSocketNotifier: Tried to unregister a not registered notifier");
        return;
    }

    // Decrement read/write counters and disable callbacks if necessary.
    if (type == QSocketNotifier::Read) {
        if (--socketInfo->read == 0)
            CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
    } else if (type == QSocketNotifier::Write) {
        if (--socketInfo->write == 0)
            CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
    }

    // Remove CFSocket from runloop if this was the last QSocketNotifier.
    if (socketInfo->read <= 0 && socketInfo->write <= 0) {
        if (CFSocketIsValid(socketInfo->socket))
            qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop);
        CFRunLoopSourceInvalidate(socketInfo->runloop);
        CFRelease(socketInfo->runloop);
        CFSocketInvalidate(socketInfo->socket);
        CFRelease(socketInfo->socket);
        delete socketInfo;
        d->macSockets.remove(nativeSocket);
    }
}
Exemple #12
0
/*------------------------------------ udpPortFree ---*/
static void
udpPortFree(UdpObjectData * xx)
{
    if (xx)
    {
        xx->fClosing = true;
        if (xx->fSocket)
        {
            CFSocketInvalidate(xx->fSocket);
            CFRelease(xx->fSocket);
            xx->fSocket = NULL;
        }
        releaseObjectMemory(xx);
    }
} // udpPortFree
Exemple #13
0
/* static */ void
_ServerReleaseSocket(Server* server) {
	
    unsigned i;
    
	for (i = 0; i < (sizeof(server->_sockets) / sizeof(server->_sockets[0])); i++) {
		
		// Invalidate and release the socket if there is one.
		if (server->_sockets[i] != NULL) {
			CFSocketInvalidate(server->_sockets[i]);
			CFRelease(server->_sockets[i]);
			server->_sockets[i] = NULL;
		}
	}
}
Exemple #14
0
static void
resolve_callback(
	__unused DNSServiceRef sdRef,
	__unused DNSServiceFlags flags,
	__unused uint32_t interfaceIndex,
	__unused DNSServiceErrorType errorCode,
	Dused const char *fullName,
	const char *hostTarget,
	Dused uint16_t port,
	Dused uint16_t txtLen,
	Dused const unsigned char *txtRecord,
	void *context)
{
	struct cbinfo *info = context;
#ifdef DEBUG
	const char *p;
	char *q, *s;
	int len;

	printf("resolve: %s %s:%d  TXT %d\n", fullName, hostTarget, port, txtLen);
	if ((txtLen > 1) && ((s = malloc(txtLen+2)))) {
		p = txtRecord;
		q = s;
		len = txtLen;
		while (len > 0) {
			strncpy(q, p+1, *p);
			len -= *p + 1;
			q += *p;
			p += *p + 1;
		}
		*q = '\0';
		printf("    %s\n", s);
		free(s);
	}
#endif
	do_print(hostTarget);

	CFRunLoopRemoveSource(CFRunLoopGetCurrent(), info->rls, kCFRunLoopDefaultMode);
	CFRelease(info->rls);
	CFSocketInvalidate(info->sockref);
	CFRelease(info->sockref);
	DNSServiceRefDeallocate(info->sdref);
	free(info);
}
void KprZeroconfPlatformServiceDispose(KprZeroconfPlatformService self)
{
	if (self) {
#if KPR_ZEROCONF_EMBEDDED
		gEmbeddedServiceCount--;
		if (!gEmbeddedServiceCount) {
			FskTimeCallbackDispose(gEmbeddedServiceTimer);
			gEmbeddedServiceTimer = NULL;
		}
#elif TARGET_OS_MAC
		if (self->source) {
			CFRunLoopRemoveSource(CFRunLoopGetCurrent(), self->source, kCFRunLoopCommonModes);
			CFRelease(self->source);
			self->source = NULL;
		}
		if (self->socket) {
			CFSocketInvalidate(self->socket);
			CFRelease(self->socket);
			self->socket = NULL;
		}
#else
		FskSocketActivate(self->source, false);
		if (self->handler) {
			FskThreadRemoveDataHandler(&self->handler);
			self->handler = NULL;
		}
		if (self->source) {
			FskMemPtrDispose(self->source);
			self->source = NULL;
		}
#endif
		if (self->serviceRef) {
			DNSServiceRefDeallocate(self->serviceRef);
			self->serviceRef = NULL;
		}
		FskMemPtrDispose(self->txt);
		FskMemPtrDispose(self->name);
		FskInstrumentedItemDispose(self);
		FskMemPtrDispose(self);
	}
}
/*!
    Implements the GUI-specific AddProcessCallback() for both wxMac and
    wxCocoa using the CFSocket/CFRunLoop API which is available to both.
    Takes advantage of the fact that sockets on UNIX are just regular
    file descriptors and thus even a non-socket file descriptor can
    apparently be used with CFSocket so long as you only tell CFSocket
    to do things with it that would be valid for a non-socket fd.
 */
int wxGUIAppTraits::AddProcessCallback(wxEndProcessData *proc_data, int fd)
{
    static int s_last_tag = 0;
    CFSocketContext context =
    {   0
    ,   static_cast<void*>(proc_data)
    ,   NULL
    ,   NULL
    ,   NULL
    };
    CFSocketRef cfSocket = CFSocketCreateWithNative(kCFAllocatorDefault,fd,kCFSocketReadCallBack,&WXCF_EndProcessDetector,&context);
    if(cfSocket == NULL)
    {
        wxLogError(wxT("Failed to create socket for end process detection"));
        return 0;
    }
    CFRunLoopSourceRef runLoopSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, cfSocket, /*highest priority:*/0);
    if(runLoopSource == NULL)
    {
        wxLogError(wxT("Failed to create CFRunLoopSource from CFSocket for end process detection"));
        // closes the fd.. we can't really stop it, nor do we necessarily want to.
        CFSocketInvalidate(cfSocket);
        CFRelease(cfSocket);
        return 0;
    }
    // Now that the run loop source has the socket retained and we no longer
    // need to refer to it within this method, we can release it.
    CFRelease(cfSocket);

    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
    // Now that the run loop has the source retained we can release it.
    CFRelease(runLoopSource);

    /*
        Feed wx some bullshit.. we don't use it since CFSocket helpfully passes
        itself into our callback and that's enough to be able to
        CFSocketInvalidate it which is all we need to do to get everything we
        just created to be deallocated.
     */
    return ++s_last_tag;
}
QEventDispatcherMac::~QEventDispatcherMac()
{
    Q_D(QEventDispatcherMac);
    //timer cleanup
    d->zero_timer_count = 0;
    if(d->macTimerList) {
        for (int i = 0; i < d->macTimerList->size(); ++i) {
            const MacTimerInfo &t = d->macTimerList->at(i);
            if (t.mac_timer) {
                RemoveEventLoopTimer(t.mac_timer);
                if (t.pending) {
                    EventComparatorUPP fnc = NewEventComparatorUPP(find_timer_event);
                    FlushSpecificEventsFromQueue(GetMainEventQueue(), fnc, (void *)&t);
                    DisposeEventComparatorUPP(fnc);
                }
            }
        }
        delete d->macTimerList;
        d->macTimerList = 0;
    }
    if(timerUPP) {
        DisposeEventLoopTimerUPP(timerUPP);
        timerUPP = 0;
    }

    // Remove CFSockets from the runloop.
    for (MacSocketHash::ConstIterator it = d->macSockets.constBegin(); it != d->macSockets.constEnd(); ++it) {
        MacSocketInfo *socketInfo = (*it);
        if (CFSocketIsValid(socketInfo->socket)) {
            qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop);
            CFRunLoopSourceInvalidate(socketInfo->runloop);
            CFRelease(socketInfo->runloop);
            CFSocketInvalidate(socketInfo->socket);
            CFRelease(socketInfo->socket);
        }
    }
    CFRunLoopRemoveSource(runLoopForCarbonLoop(GetMainEventLoop()), d->postedEventsSource, kCFRunLoopCommonModes);
    CFRelease(d->postedEventsSource);
    d->postedEventsSource = 0;
}
static void
MyDNSServiceFree(MyDNSServiceState *ref)
{
    assert(ref);
    
    if (ref->socket) {
        //Invalidate the CFSocket.
        CFSocketInvalidate(ref->socket);
        CFRelease(ref->socket);

        // Workaround that gives time to CFSocket's select thread so it can remove the socket from its
        // FD set before we close the socket by calling DNSServiceRefDeallocate. <rdar://problem/3585273>
        usleep(1000);
    }
    
    if (ref->service) {
        // Terminate the connection with the mDNSResponder daemon, which cancels the operation.
        DNSServiceRefDeallocate(ref->service);
    }
    
    free(ref);
}
/*!
    Called due to source signal detected by the CFRunLoop.
    This is nearly identical to the wxGTK equivalent.
 */
extern "C" void WXCF_EndProcessDetector(CFSocketRef s,
                                        CFSocketCallBackType WXUNUSED(callbackType),
                                        CFDataRef WXUNUSED(address),
                                        void const *WXUNUSED(data),
                                        void *info)
{
    /*
        Either our pipe was closed or the process ended successfully.  Either way,
        we're done.  It's not if waitpid is going to magically succeed when
        we get fired again.  CFSocketInvalidate closes the fd for us and also
        invalidates the run loop source for us which should cause it to
        release the CFSocket (thus causing it to be deallocated) and remove
        itself from the runloop which should release it and cause it to also
        be deallocated.  Of course, it's possible the RunLoop hangs onto
        one or both of them by retaining/releasing them within its stack
        frame.  However, that shouldn't be depended on.  Assume that s is
        deallocated due to the following call.
     */
    CFSocketInvalidate(s);

    // Now tell wx that the process has ended.
    wxHandleProcessTermination(static_cast<wxEndProcessData *>(info));
}
Exemple #20
0
static int _cf_source_schedule( struct MIDIRunloopSource * source, int event ) {
  int i, created;
  struct CFMIDIRunLoopSource * cf = source->scheduler;
  CFSocketContext socket_context;
  CFOptionFlags   socket_cb_types = kCFSocketNoCallBack;
  CFSocketRef     socket;

  if( event & MIDI_RUNLOOP_READ )  socket_cb_types |= kCFSocketReadCallBack;
  if( event & MIDI_RUNLOOP_WRITE ) socket_cb_types |= kCFSocketWriteCallBack;

  socket_context.version = 0;
  socket_context.info = source;
  socket_context.release = NULL;
  socket_context.retain  = NULL;
  socket_context.copyDescription = NULL;

  for( i=0; i<source->nfds; i++ ) {
    created = 0;
    if( FD_ISSET(i, &(source->readfds)) ) {
      created = 1;
    }
    if( FD_ISSET(i, &(source->writefds)) ) {
      created = 1;
    }
    if( created ) {
      socket = CFSocketCreateWithNative( NULL, i, socket_cb_types, &_cf_socket_callback, &socket_context );
      if( event & MIDI_RUNLOOP_INVALIDATE ) {
        CFSocketInvalidate( socket );
      } else if( socket_cb_types != kCFSocketNoCallBack ) {
        CFSocketEnableCallBacks( socket, socket_cb_types );
      }
      CFRelease( socket );
    }
  }
  return 0;
}
bool wxServiceDiscoveryTaskBase::Stop( void )
{
	bool output = false;
	
	if ( ! m_bUseThreads )
	{
		#ifdef __DARWIN__
		
			if ( ( CFRunLoopGetCurrent() != NULL ) && 
				 ( source != NULL ) &&
				 ( cfsocket != NULL ) )
			{
				// Remove the CFRunLoopSource from the current run loop. 
				CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes); 
				CFRelease(source); 
				// Invalidate the CFSocket. 
				CFSocketInvalidate(cfsocket); 
				CFRelease(cfsocket); 
				
				cfsocket = NULL;
				source = NULL;
				
				// Workaround to give time to CFSocket's select() thread 
				// so it can remove the socket from its FD set before we 
				// close the socket by calling DNSServiceRefDeallocate. 
				usleep(1000); 
			}
			
		#elif defined( _WIN32 )
			
			if ( wind != NULL )
			{
				// Clean up. This is not strictly necessary since the normal 
				// process cleanup will close DNS-SD socket(s) and release memory, 
				// but it's here to demonstrate how to do it. 
//				WSAAsyncSelect( dns_sd_fd,
//								wind, 
//								DNSSD_EVENT,
//								0 );
				
				DestroyWindow( wind );
				
				wind = NULL;
			}
			
		#endif
	}
	
	
	if ( m_rServiceRef != NULL )
	{
		// Order is important.  We deallocate the DNSServiceRef *prior* to deleting
		// the thread.  The thread is blocking permanently for a response on this
		// service reference.  If we delete the thread first, we wind up in a
		// deadlock situation.  If we delete the service first, we get an error,
		// but at least the thread stops.  As long as we prepare for that error,
		// everything will be fine.
		
		DNSServiceRefDeallocate( m_rServiceRef );
		m_rServiceRef = NULL;
		output = true;
	}
	
	if ( m_bUseThreads )
	{
		if ( m_pThread != NULL )
		{
			m_pThread->Delete();
			delete m_pThread;
			m_pThread = NULL;
		}
	}
	
	return output;
}
Exemple #22
0
/* static */ void
_DomainEnumReply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
				 DNSServiceErrorType errorCode, const char* replyDomain, void* context)
{
	__CFNetServiceBrowser* browser = context;
	CFNetServiceBrowserClientCallBack cb = NULL;
	CFStreamError error;
	void* info = NULL;
	CFStringRef domain = NULL;

	// Retain here to guarantee safety really after the trigger release,
	// but definitely before the callback.
	CFRetain(browser);

	// Lock the browser
	__CFSpinLock(&browser->_lock);

	// If the browse canceled, don't need to do any of this.
	if (browser->_browse) {

		// If there is an error, fold the browse.
		if (errorCode) {

			// Save the error
			browser->_error.error = _DNSServiceErrorToCFNetServiceError(errorCode);
			browser->_error.domain = kCFStreamErrorDomainNetServices;

			// Remove the browse from run loops and modes
			_CFTypeUnscheduleFromMultipleRunLoops(browser->_trigger, browser->_schedules);

			// Go ahead and invalidate the socket
			CFSocketInvalidate((CFSocketRef)(browser->_trigger));

			// Release the browse now.
			CFRelease(browser->_trigger);
			browser->_trigger = NULL;

			// Clean up the underlying service discovery stuff
			DNSServiceRefDeallocate(browser->_browse);
			browser->_browse = NULL;
		}

		// If got a domain from service discovery, create the CFString for the domain.
		else if (replyDomain) {
			domain = CFStringCreateWithCString(CFGetAllocator(browser),
											   replyDomain,
											   kCFStringEncodingUTF8);
		}

		cb = browser->_callback;

		// Save the error and client information for the callback
		memmove(&error, &(browser->_error), sizeof(error));
		info = browser->_client.info;

	}

	// Unlock the browser so the callback can be made safely.
	__CFSpinUnlock(&browser->_lock);

	// If there is a callback, inform the client of the finish.
	if (cb && domain) {

		// Time to translate the service discovery flags into CFNetServices
		// flags.  This is known to be a domain, so start there.
		UInt32 f = kCFNetServiceFlagIsDomain;

		// If more is coming, set that bit.
		if (flags & kDNSServiceFlagsMoreComing)
			f |= kCFNetServiceFlagMoreComing;

		// SD notifies that it's adding.  CFNetServices needs to translate to
		// ones that are going away.
		if (!(flags & kDNSServiceFlagsAdd))
			f |= kCFNetServiceFlagRemove;

		// Set the bit if this is a registration domain
		if (flags & kDNSServiceFlagsDefault)
			f |= kCFNetServiceFlagIsDefault;

		// Inform the client.
		cb((CFNetServiceBrowserRef)browser, f, domain, &error, info);
	}

	// No longer need this after the callback
	if (domain)
		CFRelease(domain);

	// Go ahead and release now that the callback is done.
	CFRelease(browser);
}
/*
    Register a QSocketNotifier with the mac event system by creating a CFSocket with
    with a read/write callback.

    Qt has separate socket notifiers for reading and writing, but on the mac there is
    a limitation of one CFSocket object for each native socket.
*/
void QEventDispatcherMac::registerSocketNotifier(QSocketNotifier *notifier)
{
    Q_ASSERT(notifier);
    int nativeSocket = notifier->socket();
    int type = notifier->type();
#ifndef QT_NO_DEBUG
    if (nativeSocket < 0 || nativeSocket > FD_SETSIZE) {
        qWarning("QSocketNotifier: Internal error");
        return;
    } else if (notifier->thread() != thread()
               || thread() != QThread::currentThread()) {
        qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread");
        return;
    }
#endif

    Q_D(QEventDispatcherMac);
    QEventDispatcherUNIX::registerSocketNotifier(notifier);

    if (type == QSocketNotifier::Exception) {
        qWarning("QSocketNotifier::Exception is not supported on Mac OS X");
        return;
    }

    // Check if we have a CFSocket for the native socket, create one if not.
    MacSocketInfo *socketInfo = d->macSockets.value(nativeSocket);
    if (!socketInfo) {
        socketInfo = new MacSocketInfo();

        // Create CFSocket, specify that we want both read and write callbacks (the callbacks
        // are enabled/disabled later on).
        const int callbackTypes = kCFSocketReadCallBack | kCFSocketWriteCallBack;
        CFSocketContext context = {0, this, NULL, NULL, NULL};
        socketInfo->socket = CFSocketCreateWithNative(kCFAllocatorDefault, nativeSocket, callbackTypes, qt_mac_socket_callback, &context);
        if (CFSocketIsValid(socketInfo->socket) == false) {
            qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to create CFSocket");
            return;
        }

        CFOptionFlags flags = CFSocketGetSocketFlags(socketInfo->socket);
        flags |= kCFSocketAutomaticallyReenableWriteCallBack; //QSocketNotifier stays enabled after a write
        flags &= ~kCFSocketCloseOnInvalidate; //QSocketNotifier doesn't close the socket upon destruction/invalidation
        CFSocketSetSocketFlags(socketInfo->socket, flags);

        // Add CFSocket to runloop.
        if(!(socketInfo->runloop = qt_mac_add_socket_to_runloop(socketInfo->socket))) {
            qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to add CFSocket to runloop");
            CFSocketInvalidate(socketInfo->socket);
            CFRelease(socketInfo->socket);
            return;
        }

        // Disable both callback types by default. This must be done after
        // we add the CFSocket to the runloop, or else these calls will have
        // no effect.
        CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
        CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);

        d->macSockets.insert(nativeSocket, socketInfo);
    }

    // Increment read/write counters and select enable callbacks if necessary.
    if (type == QSocketNotifier::Read) {
        if (++socketInfo->read == 1)
             CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack);
    } else if (type == QSocketNotifier::Write) {
        if (++socketInfo->write == 1)
             CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack);
    }
}
Exemple #24
0
/* static */ void
_BrowseReply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
			 DNSServiceErrorType errorCode, const char* serviceName, const char* regtype,
			 const char* replyDomain, void* context)
{
	__CFNetServiceBrowser* browser = context;
	CFNetServiceBrowserClientCallBack cb = NULL;
	CFStreamError error = {0, 0};
	void* info = NULL;
	CFNetServiceRef service = NULL;

	// Retain here to guarantee safety really after the trigger release,
	// but definitely before the callback.
	CFRetain(browser);

	// Lock the browser
	__CFSpinLock(&browser->_lock);

	// If the browse canceled, don't need to do any of this.
	if (browser->_browse) {

		// If there is an error, fold the browse.
		if (errorCode) {

			// Save the error
			browser->_error.error = _DNSServiceErrorToCFNetServiceError(errorCode);
			browser->_error.domain = kCFStreamErrorDomainNetServices;

			// Remove the browse from run loops and modes
			_CFTypeUnscheduleFromMultipleRunLoops(browser->_trigger, browser->_schedules);

			// Go ahead and invalidate the socket
			CFSocketInvalidate((CFSocketRef)(browser->_trigger));

			// Release the browse now.
			CFRelease(browser->_trigger);
			browser->_trigger = NULL;

			// Clean up the underlying service discovery stuff
			DNSServiceRefDeallocate(browser->_browse);
			browser->_browse = NULL;

			// Dump all the lists of items.
			CFDictionaryRemoveAllValues(browser->_found);
			CFArrayRemoveAllValues(browser->_adds);
			CFArrayRemoveAllValues(browser->_removes);
		}

		// If got service info from service discovery, create the CFNetServiceRef.
		else if (serviceName && regtype && replyDomain) {

			// Create CFString's for each of the service components
			CFAllocatorRef alloc = CFGetAllocator(browser);
			CFStringRef domain = CFStringCreateWithCString(alloc, replyDomain, kCFStringEncodingUTF8);
			CFStringRef type = CFStringCreateWithCString(alloc, regtype, kCFStringEncodingUTF8);
			CFStringRef name = CFStringCreateWithCString(alloc, serviceName, kCFStringEncodingUTF8);

			// Can only make the service if all the strings were created.  This
			// will skip over items that are not properly UTF8 encoded on the wire.
			if (domain && type && name)
				service = _CFNetServiceCreateCommon(alloc, domain, type, name, 0);

			if (domain) CFRelease(domain);
			if (type) CFRelease(type);
			if (name) CFRelease(name);

			if (service) {

				intptr_t count = (intptr_t)CFDictionaryGetValue(browser->_found, service);

				if (flags & kDNSServiceFlagsAdd) {

					count++;

					if (count != 1)
						CFDictionaryReplaceValue(browser->_found, service, (const void*)count);

					else {
						CFIndex i = CFArrayGetFirstIndexOfValue(browser->_removes,
																CFRangeMake(0, CFArrayGetCount(browser->_removes)),
																service);

						CFDictionaryAddValue(browser->_found, service, (const void*)count);
						CFArrayAppendValue(browser->_adds, service);

						if (i != kCFNotFound)
							CFArrayRemoveValueAtIndex(browser->_removes, i);
					}
				}

				else {

					count--;
					if (count > 0)
						CFDictionaryReplaceValue(browser->_found, service, (const void*)count);
					else {
						CFIndex i = CFArrayGetFirstIndexOfValue(browser->_adds,
																CFRangeMake(0, CFArrayGetCount(browser->_adds)),
																service);

						CFDictionaryRemoveValue(browser->_found, service);
						CFArrayAppendValue(browser->_removes, service);

						if (i != kCFNotFound)
							CFArrayRemoveValueAtIndex(browser->_adds, i);
					}
				}

				CFRelease(service);
			}
		}

		cb = browser->_callback;

		// Save the error and client information for the callback
		memmove(&error, &(browser->_error), sizeof(error));
		info = browser->_client.info;

	}

	// If there is a callback, inform the client of the error.
	if (cb && error.error) {

		// Unlock the browser so the callback can be made safely.
		__CFSpinUnlock(&browser->_lock);

		cb((CFNetServiceBrowserRef)browser, 0, NULL, &error, info);
	}

	else if (cb && ((flags & kDNSServiceFlagsMoreComing) == 0)) {

		CFIndex i, adds = CFArrayGetCount(browser->_adds);
		CFIndex removes = CFArrayGetCount(browser->_removes);
		CFIndex total = adds + removes;

		for (i = 0; i < adds; i++) {

			const void* saved = browser->_trigger;
			service = (CFNetServiceRef)CFArrayGetValueAtIndex(browser->_adds, i);

			// Unlock the browser so the callback can be made safely.
			__CFSpinUnlock(&browser->_lock);

			cb((CFNetServiceBrowserRef)browser,
			   (i == (total - 1)) ? 0 : kCFNetServiceFlagMoreComing,
			   service,
			   &error,
			   info);

			// Lock the browser
			__CFSpinLock(&browser->_lock);

			if (saved != browser->_trigger) {
				cb = NULL;
				break;
			}
		}

		if (cb) {
			for (i = 0; i < removes; i++) {

				const void* saved = browser->_trigger;
				service = (CFNetServiceRef)CFArrayGetValueAtIndex(browser->_removes, i);

				// Unlock the browser so the callback can be made safely.
				__CFSpinUnlock(&browser->_lock);

				cb((CFNetServiceBrowserRef)browser,
				   kCFNetServiceFlagRemove | ((i == (removes - 1)) ? 0 : kCFNetServiceFlagMoreComing),
				   service,
				   &error,
				   info);

				// Lock the browser
				__CFSpinLock(&browser->_lock);

				if (saved != browser->_trigger)
					break;
			}
		}

		// Dump the lists of items, so can start new again.
		CFArrayRemoveAllValues(browser->_adds);
		CFArrayRemoveAllValues(browser->_removes);

		// Unlock the browser so the callback can be made safely.
		__CFSpinUnlock(&browser->_lock);
	}
	else
		__CFSpinUnlock(&browser->_lock);

	// Go ahead and release now that the callback is done.
	CFRelease(browser);
}
Exemple #25
0
static void ConnectionShutdown(ConnectionRef conn)
    // This routine shuts down down the connection to the server 
    // without saying goodbye; it leaves conn valid.  This routine 
    // is primarily used internally to the connection abstraction 
    // where we notice that the connection has failed for some reason. 
    // It's also called by the client after a successful quit RPC 
    // because we know that the server has closed its end of the 
    // connection.
    //
    // It's important to nil out the fields as we close them because 
    // this routine is called if any messaging routine fails.  If it 
    // doesn't nil out the fields, two bad things might happen:
    //
    // o When the connection is eventually closed, ConnectionCloseInternal 
    //   will try to send a Goodbye, which fails triggering an assert.
    //
    // o If ConnectionShutdown is called twice on a particular connection 
    //   (which happens a lot; this is a belts and braces implementation 
    //   [that's "belts and suspenders" for the Americans reading this; 
    //   ever wonder why Monty Python's lumberjacks sing about "suspenders 
    //   and a bra"?; well look up "suspenders" in a non-American dictionary 
    //   for a quiet chuckle :-] )
{
    int     junk;
    Boolean hadSockCF;

    assert(conn != NULL);
    
    conn->fCallback       = NULL;
    conn->fCallbackRefCon = NULL;

    if (conn->fRunLoopSource != NULL) {
        CFRunLoopSourceInvalidate(conn->fRunLoopSource);
        
        CFRelease(conn->fRunLoopSource);
        
        conn->fRunLoopSource = NULL;
    }
    
    // CFSocket will close conn->fSockFD when we invalidate conn->fSockCF, 
    // so we remember whether we did this so that, later on, we know 
    // whether to close the file descriptor ourselves.  We need an extra 
    // variable because we NULL out fSockCF as we release it, for the reason 
    // described above.
    
    hadSockCF = (conn->fSockCF != NULL);
    if (conn->fSockCF != NULL) {
        CFSocketInvalidate(conn->fSockCF);
        
        CFRelease(conn->fSockCF);
        
        conn->fSockCF = NULL;
    }

    if (conn->fBufferedPackets != NULL) {
        CFRelease(conn->fBufferedPackets);
        conn->fBufferedPackets = NULL;
    }

    if ( (conn->fSockFD != -1) && ! hadSockCF ) {
        junk = close(conn->fSockFD);
        assert(junk == 0);
    }
    // We always set fSockFD to -1 because either we've closed it or 
    // CFSocket has.
    conn->fSockFD = -1;
}
Exemple #26
0
/*------------------------------------ udpPortSetPort ---*/
bool
udpPortSetPort(UdpObjectData * xx,
               const bool      bangOnError)
{
    bool okSoFar = true;

    if (xx)
    {
        if (xx->fSocket)
        {
            CFSocketInvalidate(xx->fSocket);
            CFRelease(xx->fSocket);
            xx->fSocket = NULL;
        }
        int err;
        int sock = socket(AF_INET, SOCK_DGRAM, 0);

        if (0 > sock)
        {
            err = errno;
            okSoFar = false;
        }
        else
        {
            err = 0;
        }
        if (okSoFar)
        {
            sockaddr_in addr;

            memset(&addr, 0, sizeof(addr));
            addr.sin_len = sizeof(addr);
            addr.sin_family = AF_INET;
            addr.sin_port = htons(xx->fSelfPort);
            addr.sin_addr.s_addr = INADDR_ANY;
            err = bind(sock, reinterpret_cast<sockaddr *>(&addr), sizeof(addr));
            if (0 > err)
            {
                err = errno;
                okSoFar = false;
            }
        }
        if (okSoFar)
        {
            int flags = fcntl(sock, F_GETFL);

            err = fcntl(sock, F_SETFL, flags | O_NONBLOCK);
            if (0 > err)
            {
                err = errno;
                okSoFar = false;
            }
        }
        if (okSoFar)
        {
            const CFSocketContext context = { 0, xx, NULL, NULL, NULL };

            xx->fSocket = CFSocketCreateWithNative(kCFAllocatorDefault, sock, kCFSocketReadCallBack,
                                                   socketReadCallback, &context);
            sock = -1;
            CFRunLoopSourceRef rls = CFSocketCreateRunLoopSource(kCFAllocatorDefault, xx->fSocket,
                                                                 0);

            CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
            CFRelease(rls);
            setObjectState(xx, kUdpStateBound);
        }
        if (! okSoFar)
        {
            close(sock);
            LOG_ERROR_2(xx, OUTPUT_PREFIX "set port failed (%ld)", static_cast<long>(err))
            if (bangOnError)
            {
                signalError(xx);
            }
        }
    }