mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 00:41:02 +00:00
NSPort cleanup and bugfixes.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@21936 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
58f48e81e3
commit
96cbb52e59
7 changed files with 204 additions and 86 deletions
|
@ -7,6 +7,15 @@
|
|||
the new process tries to use the same name.
|
||||
* Source/Additions/GSCategories.m: ([uuencodeInto:name:mode:]) fix
|
||||
error encoding the termination marker of the uuencoded data.
|
||||
* Headers/Foundation/NSPort.h: Declare missing category of NSObject
|
||||
Remove some of the subclass stuff that should be private.
|
||||
* Source/GSPortPrivate.h: Put private port stuff here ... needs
|
||||
more to be moved out of NSPort.h
|
||||
* Source/NSMessagePort.m: Hide instance variables. Use GSPortPrivate.h
|
||||
Add bugfix for possible deadlock situation reported by Wim.
|
||||
* Source/NSSocketPort.m: ditto
|
||||
* Source/NSMessagePortNameServer.m: Use GSPortPrivate.h
|
||||
* Source/NSPort.m: Implement missing informal protocol method.
|
||||
|
||||
2005-10-31 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
|
|
|
@ -47,6 +47,14 @@
|
|||
@class NSPortMessage;
|
||||
@class NSHost;
|
||||
|
||||
@interface NSObject(NSPortDelegateMethods)
|
||||
/**
|
||||
* Subclasses of NSPort send this message to their delegate on receipt
|
||||
* of a port message.
|
||||
*/
|
||||
- (void) handlePortMessage: (NSPortMessage*)aMessage;
|
||||
@end
|
||||
|
||||
/**
|
||||
* Exception raised by [NSPort], [NSConnection], and friends if sufficient
|
||||
* time elapses while waiting for a response, or if the receiving port is
|
||||
|
@ -175,8 +183,6 @@ GS_EXPORT NSString* const NSPortDidBecomeInvalidNotification;
|
|||
*/
|
||||
typedef SOCKET NSSocketNativeHandle;
|
||||
|
||||
@class GSTcpHandle;
|
||||
|
||||
/**
|
||||
* <p>An [NSPort] implementation for network object communications based on
|
||||
* BSD sockets. Can be used for interthread/interprocess
|
||||
|
@ -223,11 +229,6 @@ typedef SOCKET NSSocketNativeHandle;
|
|||
forceAddress: (NSString*)addr
|
||||
listener: (BOOL)shouldListen;
|
||||
|
||||
/**
|
||||
* Setup method: add new send or receive connection handle.
|
||||
*/
|
||||
- (void) addHandle: (GSTcpHandle*)handle forSend: (BOOL)send;
|
||||
|
||||
/**
|
||||
* Returns IP address of underlying socket.
|
||||
*/
|
||||
|
@ -239,12 +240,6 @@ typedef SOCKET NSSocketNativeHandle;
|
|||
*/
|
||||
- (void) getFds: (int*)fds count: (int*)count;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
- (GSTcpHandle*) handleForPort: (NSSocketPort*)recvPort
|
||||
beforeDate: (NSDate*)when;
|
||||
|
||||
/**
|
||||
* Delegates processing of a message.
|
||||
*/
|
||||
|
@ -260,14 +255,6 @@ typedef SOCKET NSSocketNativeHandle;
|
|||
*/
|
||||
- (gsu16) portNumber;
|
||||
|
||||
/**
|
||||
* This is called when a TCP/IP socket connection is broken. We remove the
|
||||
* connection handle from this port and, if this was the last handle to a
|
||||
* remote port, we invalidate the port.
|
||||
*/
|
||||
- (void) removeHandle: (GSTcpHandle*)handle;
|
||||
|
||||
|
||||
// This is the OS X interface
|
||||
/*
|
||||
{
|
||||
|
@ -304,54 +291,15 @@ typedef SOCKET NSSocketNativeHandle;
|
|||
@end
|
||||
|
||||
|
||||
@class GSMessageHandle;
|
||||
|
||||
/**
|
||||
* An [NSPort] implementation for network object communications based on
|
||||
* Unix domain sockets. Can be used for interthread/interprocess
|
||||
* communications on the same host, but not between different hosts.
|
||||
* An [NSPort] implementation for network object communications
|
||||
* which can be used for interthread/interprocess communications
|
||||
* on the same host, but not between different hosts.
|
||||
*/
|
||||
@interface NSMessagePort : NSPort <GCFinalization>
|
||||
{
|
||||
NSData *name;
|
||||
NSRecursiveLock *myLock;
|
||||
NSMapTable *handles; /* Handles indexed by socket. */
|
||||
int listener; /* Descriptor to listen on. */
|
||||
#if defined(__MINGW32__)
|
||||
WSAEVENT eventListener;
|
||||
NSMapTable *events;
|
||||
#endif
|
||||
void *_internal;
|
||||
}
|
||||
|
||||
- (int) _listener;
|
||||
- (const unsigned char *) _name;
|
||||
|
||||
/**
|
||||
* <init/>
|
||||
* This is the preferred initialisation method for <code>NSMessagePort</code>.
|
||||
*
|
||||
* socketName is the name of the socket in the port directory
|
||||
*/
|
||||
+ (NSMessagePort*) _portWithName: (const unsigned char *)socketName
|
||||
listener: (BOOL)shouldListen;
|
||||
|
||||
/**
|
||||
* Setup method: add new send or receive connection handle.
|
||||
*/
|
||||
- (void) addHandle: (GSMessageHandle*)handle forSend: (BOOL)send;
|
||||
|
||||
/**
|
||||
* This is called when a socket connection is broken. We remove the
|
||||
* connection handle from this port and, if this was the last handle to a
|
||||
* remote port, we invalidate the port.
|
||||
*/
|
||||
- (void) removeHandle: (GSMessageHandle*)handle;
|
||||
|
||||
/**
|
||||
* Delegates processing of a message.
|
||||
*/
|
||||
- (void) handlePortMessage: (NSPortMessage*)m;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
|
48
Source/GSPortPrivate.h
Normal file
48
Source/GSPortPrivate.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/* GSPortPrivate
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __GSPortPrivate_h_
|
||||
#define __GSPortPrivate_h_
|
||||
|
||||
@class GSMessageHandle;
|
||||
|
||||
@interface NSMessagePort(Private)
|
||||
|
||||
- (int) _listener;
|
||||
- (const unsigned char *) _name;
|
||||
+ (NSMessagePort*) _portWithName: (const unsigned char *)socketName
|
||||
listener: (BOOL)shouldListen;
|
||||
- (void) addHandle: (GSMessageHandle*)handle forSend: (BOOL)send;
|
||||
- (void) removeHandle: (GSMessageHandle*)handle;
|
||||
@end
|
||||
|
||||
@class GSTcpHandle;
|
||||
|
||||
@interface NSSocketPort (Private)
|
||||
- (void) addHandle: (GSTcpHandle*)handle forSend: (BOOL)send;
|
||||
- (GSTcpHandle*) handleForPort: (NSSocketPort*)recvPort
|
||||
beforeDate: (NSDate*)when;
|
||||
- (void) removeHandle: (GSTcpHandle*)handle;
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
|
@ -42,6 +42,9 @@
|
|||
#include "Foundation/NSValue.h"
|
||||
#include "Foundation/NSFileManager.h"
|
||||
#include "Foundation/NSProcessInfo.h"
|
||||
|
||||
#include "GSPortPrivate.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
|
@ -124,6 +127,7 @@ static gsu32 maxDataLength = 10 * 1024 * 1024;
|
|||
|
||||
/* Private interfaces */
|
||||
|
||||
|
||||
/*
|
||||
* The GSPortItemType constant is used to identify the type of data in
|
||||
* each packet read. All data transmitted is in a packet, each packet
|
||||
|
@ -399,6 +403,14 @@ static Class runLoopClass;
|
|||
type: ET_EDESC
|
||||
watcher: self
|
||||
forMode: NSConnectionReplyMode];
|
||||
[l addEvent: (void*)(gsaddr)desc
|
||||
type: ET_WDESC
|
||||
watcher: self
|
||||
forMode: NSDefaultRunLoopMode];
|
||||
[l addEvent: (void*)(gsaddr)desc
|
||||
type: ET_EDESC
|
||||
watcher: self
|
||||
forMode: NSDefaultRunLoopMode];
|
||||
|
||||
while (valid == YES && state == GS_H_TRYCON
|
||||
&& [when timeIntervalSinceNow] > 0)
|
||||
|
@ -414,6 +426,14 @@ static Class runLoopClass;
|
|||
type: ET_EDESC
|
||||
forMode: NSConnectionReplyMode
|
||||
all: NO];
|
||||
[l removeEvent: (void*)(gsaddr)desc
|
||||
type: ET_WDESC
|
||||
forMode: NSDefaultRunLoopMode
|
||||
all: NO];
|
||||
[l removeEvent: (void*)(gsaddr)desc
|
||||
type: ET_EDESC
|
||||
forMode: NSDefaultRunLoopMode
|
||||
all: NO];
|
||||
|
||||
if (state == GS_H_TRYCON)
|
||||
{
|
||||
|
@ -1014,6 +1034,14 @@ static Class runLoopClass;
|
|||
type: ET_EDESC
|
||||
watcher: self
|
||||
forMode: NSConnectionReplyMode];
|
||||
[l addEvent: (void*)(gsaddr)desc
|
||||
type: ET_WDESC
|
||||
watcher: self
|
||||
forMode: NSDefaultRunLoopMode];
|
||||
[l addEvent: (void*)(gsaddr)desc
|
||||
type: ET_EDESC
|
||||
watcher: self
|
||||
forMode: NSDefaultRunLoopMode];
|
||||
|
||||
while (valid == YES
|
||||
&& [wMsgs indexOfObjectIdenticalTo: components] != NSNotFound
|
||||
|
@ -1032,6 +1060,14 @@ static Class runLoopClass;
|
|||
type: ET_EDESC
|
||||
forMode: NSConnectionReplyMode
|
||||
all: NO];
|
||||
[l removeEvent: (void*)(gsaddr)desc
|
||||
type: ET_WDESC
|
||||
forMode: NSDefaultRunLoopMode
|
||||
all: NO];
|
||||
[l removeEvent: (void*)(gsaddr)desc
|
||||
type: ET_EDESC
|
||||
forMode: NSDefaultRunLoopMode
|
||||
all: NO];
|
||||
|
||||
if ([wMsgs indexOfObjectIdenticalTo: components] == NSNotFound)
|
||||
{
|
||||
|
@ -1088,6 +1124,17 @@ static Class runLoopClass;
|
|||
|
||||
@implementation NSMessagePort
|
||||
|
||||
typedef struct {
|
||||
NSData *_name;
|
||||
NSRecursiveLock *_myLock;
|
||||
NSMapTable *_handles; /* Handles indexed by socket. */
|
||||
int _listener; /* Descriptor to listen on. */
|
||||
} internal;
|
||||
#define name ((internal*)_internal)->_name
|
||||
#define myLock ((internal*)_internal)->_myLock
|
||||
#define handles ((internal*)_internal)->_handles
|
||||
#define lDesc ((internal*)_internal)->_listener
|
||||
|
||||
static NSRecursiveLock *messagePortLock = nil;
|
||||
|
||||
/*
|
||||
|
@ -1100,16 +1147,16 @@ static Class messagePortClass;
|
|||
static void clean_up_sockets(void)
|
||||
{
|
||||
NSMessagePort *port;
|
||||
NSData *name;
|
||||
NSData *data;
|
||||
NSMapEnumerator mEnum;
|
||||
BOOL unknownThread = GSRegisterCurrentThread();
|
||||
CREATE_AUTORELEASE_POOL(arp);
|
||||
|
||||
mEnum = NSEnumerateMapTable(messagePortMap);
|
||||
while (NSNextMapEnumeratorPair(&mEnum, (void *)&name, (void *)&port))
|
||||
while (NSNextMapEnumeratorPair(&mEnum, (void *)&data, (void *)&port))
|
||||
{
|
||||
if ([port _listener] != -1)
|
||||
unlink([name bytes]);
|
||||
unlink([data bytes]);
|
||||
}
|
||||
NSEndMapTableEnumeration(&mEnum);
|
||||
DESTROY(arp);
|
||||
|
@ -1142,7 +1189,7 @@ static unsigned wordAlign;
|
|||
|
||||
+ (id) new
|
||||
{
|
||||
static int unique_index = 0;
|
||||
static int unique_index = 0;
|
||||
NSString *path;
|
||||
NSNumber *p = [NSNumber numberWithInt: 0700];
|
||||
NSDictionary *attr;
|
||||
|
@ -1195,11 +1242,14 @@ static int unique_index = 0;
|
|||
if (port == nil)
|
||||
{
|
||||
port = (NSMessagePort*)NSAllocateObject(self, 0, NSDefaultMallocZone());
|
||||
port->name = theName;
|
||||
port->listener = -1;
|
||||
port->handles = NSCreateMapTable(NSIntMapKeyCallBacks,
|
||||
port->_internal = (internal*)NSZoneMalloc(NSDefaultMallocZone(),
|
||||
sizeof(internal));
|
||||
((internal*)(port->_internal))->_name = theName;
|
||||
((internal*)(port->_internal))->_listener = -1;
|
||||
((internal*)(port->_internal))->_handles
|
||||
= NSCreateMapTable(NSIntMapKeyCallBacks,
|
||||
NSObjectMapValueCallBacks, 0);
|
||||
port->myLock = [GSLazyRecursiveLock new];
|
||||
((internal*)(port->_internal))->_myLock = [GSLazyRecursiveLock new];
|
||||
port->_is_valid = YES;
|
||||
|
||||
if (shouldListen == YES)
|
||||
|
@ -1281,7 +1331,7 @@ static int unique_index = 0;
|
|||
* number (which will have been set to a real port number when
|
||||
* we did the 'bind' call.
|
||||
*/
|
||||
port->listener = desc;
|
||||
((internal*)port->_internal)->_listener = desc;
|
||||
/*
|
||||
* Make sure we have the map table for this port.
|
||||
*/
|
||||
|
@ -1337,7 +1387,11 @@ static int unique_index = 0;
|
|||
- (void) dealloc
|
||||
{
|
||||
[self gcFinalize];
|
||||
DESTROY(name);
|
||||
if (_internal != 0)
|
||||
{
|
||||
DESTROY(name);
|
||||
NSZoneFree(NSDefaultMallocZone(), _internal);
|
||||
}
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
@ -1379,9 +1433,9 @@ static int unique_index = 0;
|
|||
* Put in our listening socket.
|
||||
*/
|
||||
*count = 0;
|
||||
if (listener >= 0)
|
||||
if (lDesc >= 0)
|
||||
{
|
||||
fds[(*count)++] = listener;
|
||||
fds[(*count)++] = lDesc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1543,11 +1597,11 @@ static int unique_index = 0;
|
|||
unsigned i;
|
||||
|
||||
M_LOCK(messagePortLock);
|
||||
if (listener >= 0)
|
||||
if (lDesc >= 0)
|
||||
{
|
||||
(void) close(listener);
|
||||
(void) close(lDesc);
|
||||
unlink([name bytes]);
|
||||
listener = -1;
|
||||
lDesc = -1;
|
||||
}
|
||||
NSMapRemove(messagePortMap, (void*)name);
|
||||
M_UNLOCK(messagePortLock);
|
||||
|
@ -1590,7 +1644,7 @@ static int unique_index = 0;
|
|||
{
|
||||
NSMessagePort *o = (NSMessagePort*)anObject;
|
||||
|
||||
return [o->name isEqual: name];
|
||||
return [((internal*)o->_internal)->_name isEqual: name];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
@ -1603,12 +1657,12 @@ static int unique_index = 0;
|
|||
int desc = (int)(gsaddr)extra;
|
||||
GSMessageHandle *handle;
|
||||
|
||||
if (desc == listener)
|
||||
if (desc == lDesc)
|
||||
{
|
||||
struct sockaddr_un sockAddr;
|
||||
unsigned size = sizeof(sockAddr);
|
||||
|
||||
desc = accept(listener, (struct sockaddr*)&sockAddr, &size);
|
||||
desc = accept(lDesc, (struct sockaddr*)&sockAddr, &size);
|
||||
if (desc < 0)
|
||||
{
|
||||
NSDebugMLLog(@"NSMessagePort",
|
||||
|
@ -1683,7 +1737,7 @@ static int unique_index = 0;
|
|||
handle->recvPort = nil;
|
||||
}
|
||||
NSMapRemove(handles, (void*)(gsaddr)[handle descriptor]);
|
||||
if (listener < 0 && NSCountMapTable(handles) == 0)
|
||||
if (lDesc < 0 && NSCountMapTable(handles) == 0)
|
||||
{
|
||||
[self invalidate];
|
||||
}
|
||||
|
@ -1894,14 +1948,14 @@ static int unique_index = 0;
|
|||
}
|
||||
|
||||
|
||||
-(const unsigned char *) _name
|
||||
- (const unsigned char *) _name
|
||||
{
|
||||
return [name bytes];
|
||||
}
|
||||
|
||||
-(int) _listener
|
||||
- (int) _listener
|
||||
{
|
||||
return listener;
|
||||
return lDesc;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include "Foundation/NSValue.h"
|
||||
#include "Foundation/NSThread.h"
|
||||
|
||||
#include "GSPortPrivate.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
|
|
@ -39,6 +39,12 @@
|
|||
|
||||
@class NSMessagePort;
|
||||
|
||||
@implementation NSObject(NSPortDelegateMethods)
|
||||
- (void) handlePortMessage: (NSPortMessage*)aMessage
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation NSPort
|
||||
|
||||
/**
|
||||
|
|
|
@ -41,6 +41,9 @@
|
|||
#include "Foundation/NSThread.h"
|
||||
#include "Foundation/NSConnection.h"
|
||||
#include "Foundation/NSDebug.h"
|
||||
|
||||
#include "GSPortPrivate.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
|
@ -570,6 +573,10 @@ static Class runLoopClass;
|
|||
type: ET_HANDLE
|
||||
watcher: self
|
||||
forMode: NSConnectionReplyMode];
|
||||
[l addEvent: (void*)(gsaddr)event
|
||||
type: ET_HANDLE
|
||||
watcher: self
|
||||
forMode: NSDefaultRunLoopMode];
|
||||
inReplyMode = YES;
|
||||
#else
|
||||
[l addEvent: (void*)(gsaddr)desc
|
||||
|
@ -580,6 +587,14 @@ static Class runLoopClass;
|
|||
type: ET_EDESC
|
||||
watcher: self
|
||||
forMode: NSConnectionReplyMode];
|
||||
[l addEvent: (void*)(gsaddr)desc
|
||||
type: ET_WDESC
|
||||
watcher: self
|
||||
forMode: NSDefaultRunLoopMode];
|
||||
[l addEvent: (void*)(gsaddr)desc
|
||||
type: ET_EDESC
|
||||
watcher: self
|
||||
forMode: NSDefaultRunLoopMode];
|
||||
#endif
|
||||
|
||||
while (valid == YES && state == GS_H_TRYCON
|
||||
|
@ -595,6 +610,10 @@ static Class runLoopClass;
|
|||
type: ET_HANDLE
|
||||
forMode: NSConnectionReplyMode
|
||||
all: NO];
|
||||
[l removeEvent: (void*)(gsaddr)event
|
||||
type: ET_HANDLE
|
||||
forMode: NSDefaultRunLoopMode
|
||||
all: NO];
|
||||
inReplyMode = NO;
|
||||
#else
|
||||
[l removeEvent: (void*)(gsaddr)desc
|
||||
|
@ -605,6 +624,14 @@ static Class runLoopClass;
|
|||
type: ET_EDESC
|
||||
forMode: NSConnectionReplyMode
|
||||
all: NO];
|
||||
[l removeEvent: (void*)(gsaddr)desc
|
||||
type: ET_WDESC
|
||||
forMode: NSDefaultRunLoopMode
|
||||
all: NO];
|
||||
[l removeEvent: (void*)(gsaddr)desc
|
||||
type: ET_EDESC
|
||||
forMode: NSDefaultRunLoopMode
|
||||
all: NO];
|
||||
#endif
|
||||
|
||||
if (state == GS_H_TRYCON)
|
||||
|
@ -1330,6 +1357,10 @@ static Class runLoopClass;
|
|||
type: ET_HANDLE
|
||||
watcher: self
|
||||
forMode: NSConnectionReplyMode];
|
||||
[l addEvent: (void*)(gsaddr)event
|
||||
type: ET_HANDLE
|
||||
watcher: self
|
||||
forMode: NSDefaultRunLoopMode];
|
||||
inReplyMode = YES;
|
||||
#else
|
||||
[l addEvent: (void*)(gsaddr)desc
|
||||
|
@ -1340,6 +1371,14 @@ static Class runLoopClass;
|
|||
type: ET_EDESC
|
||||
watcher: self
|
||||
forMode: NSConnectionReplyMode];
|
||||
[l addEvent: (void*)(gsaddr)desc
|
||||
type: ET_WDESC
|
||||
watcher: self
|
||||
forMode: NSDefaultRunLoopMode];
|
||||
[l addEvent: (void*)(gsaddr)desc
|
||||
type: ET_EDESC
|
||||
watcher: self
|
||||
forMode: NSDefaultRunLoopMode];
|
||||
#endif
|
||||
|
||||
while (valid == YES
|
||||
|
@ -1367,6 +1406,10 @@ static Class runLoopClass;
|
|||
type: ET_HANDLE
|
||||
forMode: NSConnectionReplyMode
|
||||
all: NO];
|
||||
[l removeEvent: (void*)(gsaddr)event
|
||||
type: ET_HANDLE
|
||||
forMode: NSDefaultRunLoopMode
|
||||
all: NO];
|
||||
inReplyMode = NO;
|
||||
#else
|
||||
[l removeEvent: (void*)(gsaddr)desc
|
||||
|
@ -1377,6 +1420,14 @@ static Class runLoopClass;
|
|||
type: ET_EDESC
|
||||
forMode: NSConnectionReplyMode
|
||||
all: NO];
|
||||
[l removeEvent: (void*)(gsaddr)desc
|
||||
type: ET_WDESC
|
||||
forMode: NSDefaultRunLoopMode
|
||||
all: NO];
|
||||
[l removeEvent: (void*)(gsaddr)desc
|
||||
type: ET_EDESC
|
||||
forMode: NSDefaultRunLoopMode
|
||||
all: NO];
|
||||
#endif
|
||||
|
||||
if ([wMsgs indexOfObjectIdenticalTo: components] == NSNotFound)
|
||||
|
|
Loading…
Reference in a new issue