Retain/Release and DO patches from Richard Frith-MacDonald

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@2571 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Adam Fedor 1997-10-28 14:34:49 +00:00
parent cd1c0e3508
commit dd9eaaa18b
25 changed files with 697 additions and 134 deletions

View file

@ -45,6 +45,7 @@
#include <Foundation/NSMapTable.h>
#include <Foundation/NSHashTable.h>
#include <Foundation/NSCoder.h>
#include <Foundation/NSAutoreleasePool.h>
#include <assert.h>
@ -262,7 +263,8 @@ static BOOL debug_coder = NO;
{
id ret = [[self class] newReadingFromStream:
[MemoryStream streamWithData:data]];
if ([self retainCount] == 0)
if ([self retainCount]
- [[[self class] autoreleaseClass] autoreleaseCountForObject:self] == 0)
[ret autorelease];
else
[self release];

View file

@ -375,7 +375,6 @@ hpux-load.h \
null-load.h \
simple-load.h \
NSCallBacks.h \
gdomap.c gdomap.h \
tzfile.h
BASE_HEADERS = \

View file

@ -70,7 +70,10 @@ after-uninstall::
# before-distclean::
# Things to do after distcleaning
# after-distclean::
after-distclean::
rm -f include/config.h include/dynamic-load.h \
Foundation gnustep/base \
NSNumber[0-9]*.m NSValue[0-9]*.m
# Things to do before checking
# before-check::

View file

@ -35,6 +35,7 @@
#include <Foundation/NSNotification.h>
#include <Foundation/NSLock.h>
#include <Foundation/NSMapTable.h>
#include <Foundation/NSAutoreleasePool.h>
#include <assert.h>
#include <sys/stat.h>
@ -365,8 +366,8 @@ _bundle_load_callback(Class theClass, Category *theCategory)
format: @"Bundle for path %@ released too many times", _path];
}
NSParameterAssert(_retainCount >= 0);
if (_retainCount == 0)
if ([self retainCount]
- [[[self class] autoreleaseClass] autoreleaseCountForObject:self] == 0)
{
/* Cache all bundles */
if (_bundleType == NSBUNDLE_APPLICATION
@ -380,18 +381,7 @@ _bundle_load_callback(Class theClass, Category *theCategory)
[self dealloc];
return;
}
_retainCount--;
}
- retain
{
_retainCount++;
return self;
}
- (unsigned) retainCount
{
return _retainCount;
[super release];
}
- (void) dealloc

View file

@ -74,10 +74,30 @@ static id long_month[12] = {@"January",
@"October",
@"November",
@"December"};
static id short_day[7] = {@"Sun",
@"Mon",
@"Tue",
@"Wed",
@"Thu",
@"Fri",
@"Sat"};
static id long_day[7] = {@"Sunday",
@"Monday",
@"Tuesday",
@"Wednesday",
@"Thursday",
@"Friday",
@"Saturday"};
@interface NSCalendarDate (Private)
- (void)getYear:(int *)year month:(int *)month day:(int *)day
hour:(int *)hour minute:(int *)minute second:(int *)second;
@end
@implementation NSCalendarDate
//
// Getting an NSCalendar Date
//
@ -345,11 +365,13 @@ static id long_month[12] = {@"January",
second:(unsigned int)second
timeZone:(NSTimeZone *)aTimeZone
{
int a;
int a;
int c;
NSTimeInterval s;
a = [self absoluteGregorianDay: day month: month year: year];
// Calculate date as GMT
a -= GREGORIAN_REFERENCE;
s = (double)a * 86400;
s += hour * 3600;
@ -361,7 +383,69 @@ static id long_month[12] = {@"January",
timeZoneDetailForDate:
[NSDate dateWithTimeIntervalSinceReferenceDate: s]];
return [self initWithTimeIntervalSinceReferenceDate: s];
// Adjust date so it is correct for time zone.
s -= [time_zone timeZoneSecondsFromGMT];
self = [self initWithTimeIntervalSinceReferenceDate: s];
/* Now permit up to five cycles of adjustment to allow for daylight savings.
NB. this depends on it being OK to call the
[-initWithTimeIntervalSinceReferenceDate:] method repeatedly! */
for (c = 0; c < 5 && self != nil; c++)
{
int y, m, d, h, mm, ss;
NSTimeZoneDetail *z;
[self getYear: &y month: &m day: &d hour: &h minute: &mm second: &ss];
if (y==year && m==month && d==day && h==hour && mm==minute && ss==second)
return self;
/* Has the time-zone detail changed? If so - adjust time for it,
other wise - try to adjust to the correct time. */
z = [aTimeZone
timeZoneDetailForDate:
[NSDate dateWithTimeIntervalSinceReferenceDate: s]];
if (z != time_zone)
{
NSTimeInterval oldOffset;
NSTimeInterval newOffset;
oldOffset = [time_zone timeZoneSecondsFromGMT];
time_zone = z;
newOffset = [time_zone timeZoneSecondsFromGMT];
s += oldOffset - newOffset;
}
else
{
NSTimeInterval move;
/* Do we need to go back or forwards in time?
Shift at most two hours - we know of no daylight savings time
which is an offset of more than two hourts */
if (y > year)
move = -7200.0;
else if (y < year)
move = +7200.0;
else if (m > month)
move = -7200.0;
else if (m < month)
move = +7200.0;
else if (d > day)
move = -7200.0;
else if (d < day)
move = +7200.0;
else if (h > hour || h < hour)
move = (hour - h)*3600.0;
else if (mm > minute || mm < minute)
move = (minute - mm)*60.0;
else
move = (second - ss);
s += move;
}
self = [self initWithTimeIntervalSinceReferenceDate: s];
}
return self;
}
// Default initializer
@ -428,7 +512,16 @@ static id long_month[12] = {@"January",
- (int)dayOfWeek
{
return 0;
int d = [self dayOfCommonEra];
/* The era started on a sunday.
Did we always have a seven day week?
Did we lose week days changing from Julian to Gregorian?
AFAIK seven days a week is ok for all reasonable dates. */
d = d % 7;
if (d < 0)
d += 7;
return d;
}
- (int)dayOfYear
@ -531,7 +624,12 @@ static id long_month[12] = {@"January",
minute:(unsigned int)minute
second:(unsigned int)second
{
return self;
return [self dateByAddingYears: year
months: month
days: day
hours: hour
minutes: minute
seconds: second];
}
// Getting String Descriptions of Dates
@ -555,16 +653,17 @@ static id long_month[12] = {@"January",
const char *f = [format cString];
int lf = strlen(f);
BOOL mtag = NO, dtag = NO, ycent = NO;
BOOL mname = NO;
int yd = 0, md = 0, dd = 0, hd = 0, mnd = 0, sd = 0;
int nhd;
int i, j, k;
BOOL mname = NO, dname = NO;
double s;
int yd = 0, md = 0, dd = 0, mnd = 0, sd = 0, dom = -1, dow = -1, doy = -1;
int hd = 0, nhd;
int i, j, k, z;
// If the format is nil then return an empty string
if (!format)
return @"";
[self getYear: &yd month: &md day: &dd hour: &hd minute: &mnd second: &sd];
[self getYear: &yd month: &md day: &dom hour: &hd minute: &mnd second: &sd];
nhd = hd;
// The strftime specifiers
@ -572,7 +671,9 @@ static id long_month[12] = {@"January",
// %A full weekday name according to locale
// %b abbreviated month name according to locale
// %B full month name according to locale
// %d day of month as decimal number
// %d day of month as decimal number (leading zero)
// %e day of month as decimal number (leading space)
// %F milliseconds (000 to 999)
// %H hour as a decimal number using 24-hour clock
// %I hour as a decimal number using 12-hour clock
// %j day of year as a decimal number
@ -585,6 +686,7 @@ static id long_month[12] = {@"January",
// %w day of the week as decimal number (Sunday = 0)
// %y year as a decimal number without century
// %Y year as a decimal number with century
// %z time zone offset (HHMM)
// %Z time zone
// %% literal % character
@ -638,23 +740,53 @@ static id long_month[12] = {@"January",
j += k;
break;
// is it the day
case 'd': // day of month
++i;
k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%02d", dom));
j += k;
break;
case 'e': // day of month
++i;
k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%2d", dom));
j += k;
break;
case 'F': // milliseconds
s = ([self dayOfCommonEra] - GREGORIAN_REFERENCE) * 86400.0;
s -= (seconds_since_ref+[time_zone timeZoneSecondsFromGMT]);
s = abs(s);
s -= floor(s);
++i;
k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%03d", (int)s*1000));
j += k;
break;
case 'j': // day of year
if (doy < 0) doy = [self dayOfYear];
++i;
k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%02d", doy));
j += k;
break;
// is it the week-day
case 'a':
dname = YES;
case 'A':
dtag = YES; // Day is character string
case 'd':
case 'j':
case 'w':
++i;
if (dow < 0) dow = [self dayOfWeek];
if (dtag)
{
// +++ Translate to locale character string
/* Was: k = sprintf(&(buf[j]), ""); */
buf[j] = '\0';
k = 0;
if (dname)
k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%s", [short_day[dow] cString]));
else
k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%s", [long_day[dow] cString]));
}
else
k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%02d", dd));
k = VSPRINTF_LENGTH(sprintf(&(buf[j]), "%02d", dow));
j += k;
break;
@ -701,6 +833,19 @@ static id long_month[12] = {@"January",
j += k;
break;
case 'z':
++i;
z = [time_zone timeZoneSecondsFromGMT];
if (z < 0) {
z = -z;
k = VSPRINTF_LENGTH(sprintf(&(buf[j]),"-%02d%02d",z/60,z%60));
}
else {
k = VSPRINTF_LENGTH(sprintf(&(buf[j]),"+%02d%02d",z/60,z%60));
}
j += k;
break;
// Anything else is unknown so just copy
default:
buf[j] = f[i];
@ -815,3 +960,236 @@ static id long_month[12] = {@"January",
}
@end
@implementation NSCalendarDate (OPENSTEP)
- (NSCalendarDate *)dateByAddingYears:(int)years
months:(int)months
days:(int)days
hours:(int)hours
minutes:(int)minutes
seconds:(int)seconds
{
int i, year, month, day, hour, minute, second;
[self getYear: &year
month: &month
day: &day
hour: &hour
minute: &minute
second: &second];
second += seconds;
minute += second/60;
second %= 60;
if (second < 0)
{
minute--;
second += 60;
}
minute += minutes;
hour += minute/60;
minute %= 60;
if (minute < 0)
{
hour--;
minute += 60;
}
hour += hours;
day += hour/24;
hour %= 24;
if (hour < 0)
{
day--;
hour += 24;
}
day += days;
if (day > 0)
{
i = [self lastDayOfGregorianMonth: month year: year];
while (day > i)
{
day -= i;
if (month < 12)
month++;
else
{
month = 0;
year++;
}
}
}
else
while (day < 0)
{
if (month == 1)
{
year--;
month = 12;
}
else
month--;
day += [self lastDayOfGregorianMonth: month year: year];
}
month += months;
while (month > 12)
{
year++;
month -= 12;
}
while (month < 1)
{
year--;
month += 12;
}
year += years;
return [NSCalendarDate dateWithYear:year
month:month
day:day
hour:hour
minute:minute
second:second
timeZone:nil];
}
- (void) years: (int*)years
months: (int*)months
days: (int*)days
hours: (int*)hours
minutes: (int*)minutes
seconds: (int*)seconds
sinceDate: (NSDate*)date
{
NSCalendarDate *start;
NSCalendarDate *end;
NSCalendarDate *tmp;
int diff;
int extra;
int sign;
int syear, smonth, sday, shour, sminute, ssecond;
int eyear, emonth, eday, ehour, eminute, esecond;
/* FIXME What if the two dates are in different time zones?
How about daylight savings time?
*/
if ([date isKindOfClass: [NSCalendarDate class]])
tmp = (NSCalendarDate*)[date retain];
else
tmp = [[NSCalendarDate alloc] initWithTimeIntervalSinceReferenceDate:
[date timeIntervalSinceReferenceDate]];
end = (NSCalendarDate*)[self laterDate: tmp];
if (end == self)
{
start = tmp;
sign = 1;
}
else
{
start = self;
sign = -1;
}
[start getYear: &syear
month: &smonth
day: &sday
hour: &shour
minute: &sminute
second: &ssecond];
[end getYear: &eyear
month: &emonth
day: &eday
hour: &ehour
minute: &eminute
second: &esecond];
/* Calculate year difference and leave any remaining months in 'extra' */
diff = eyear - syear;
extra = 0;
if (emonth < smonth)
{
diff--;
extra += 12;
}
if (years)
*years = sign*diff;
else
extra += diff*12;
/* Calculate month difference and leave any remaining days in 'extra' */
diff = emonth - smonth + extra;
extra = 0;
if (eday < sday)
{
diff--;
if (emonth > 1)
extra = [end lastDayOfGregorianMonth: emonth-1 year: eyear];
else
extra = 31;
}
if (months)
*months = sign*diff;
else
{
while (diff--) {
if (emonth - diff >= 1)
extra += [end lastDayOfGregorianMonth: emonth-diff year: eyear];
else
extra += [end lastDayOfGregorianMonth: emonth-diff+12 year: eyear-1];
}
}
/* Calculate day difference and leave any remaining hours in 'extra' */
diff = eday - sday + extra;
extra = 0;
if (ehour < shour)
{
diff--;
extra = 24;
}
if (days)
*days = sign*diff;
else
extra += diff*24;
/* Calculate hour difference and leave any remaining minutes in 'extra' */
diff = ehour - shour + extra;
extra = 0;
if (eminute < sminute)
{
diff--;
extra = 60;
}
if (hours)
*hours = sign*diff;
else
extra += diff*60;
/* Calculate minute difference and leave any remaining seconds in 'extra' */
diff = eminute - sminute + extra;
extra = 0;
if (esecond < ssecond)
{
diff--;
extra = 60;
}
if (minutes)
*minutes = sign*diff;
else
extra += diff*60;
diff = esecond - ssecond + extra;
if (seconds)
*seconds = sign*diff;
[tmp release];
}
@end

View file

@ -81,7 +81,8 @@
#include <sys/ipc.h>
#include <sys/shm.h>
#define VM_ACCESS 0644 /* self read/write - other readonly */
#define VM_RDONLY 0644 /* self read/write - other readonly */
#define VM_ACCESS 0666 /* read/write access for all */
@class NSDataShared;
@class NSMutableDataShared;
#endif
@ -1334,7 +1335,18 @@ readContentsOfFile(NSString* path, void** buf, unsigned* len)
{
if (bytes)
{
shmdt(bytes);
struct shmid_ds buf;
if (shmctl(shmid, IPC_STAT, &buf) < 0)
NSLog(@"[NSDataShared -dealloc] shared memory control failed - %s",
strerror(errno));
else if (buf.shm_nattch == 1)
if (shmctl(shmid, IPC_RMID, &buf) < 0) /* Mark for deletion. */
NSLog(@"[NSDataShared -dealloc] shared memory delete failed - %s",
strerror(errno));
if (shmdt(bytes) < 0)
NSLog(@"[NSDataShared -dealloc] shared memory detach failed - %s",
strerror(errno));
bytes = 0;
length = 0;
shmid = -1;
@ -1352,7 +1364,7 @@ readContentsOfFile(NSString* path, void** buf, unsigned* len)
shmid = -1;
if (aBuffer && bufferSize)
{
shmid = shmget(IPC_PRIVATE, bufferSize, IPC_CREAT|VM_ACCESS);
shmid = shmget(IPC_PRIVATE, bufferSize, IPC_CREAT|VM_RDONLY);
if (shmid == -1) /* Created memory? */
{
NSLog(@"[-initWithBytes:length:] shared mem get failed for %u - %s",
@ -1363,7 +1375,6 @@ readContentsOfFile(NSString* path, void** buf, unsigned* len)
}
bytes = shmat(shmid, 0, 0);
shmctl(shmid, IPC_RMID, &buf); /* Mark for later deletion. */
if (bytes == (void*)-1)
{
NSLog(@"[-initWithBytes:length:] shared mem attach failed for %u - %s",
@ -1670,7 +1681,15 @@ readContentsOfFile(NSString* path, void** buf, unsigned* len)
{
if (bytes)
{
shmdt(bytes);
struct shmid_ds buf;
if (shmctl(shmid, IPC_STAT, &buf) < 0)
NSLog(@"[NSMutableDataShared -dealloc] shared memory control failed - %s", strerror(errno));
else if (buf.shm_nattch == 1)
if (shmctl(shmid, IPC_RMID, &buf) < 0) /* Mark for deletion. */
NSLog(@"[NSMutableDataShared -dealloc] shared memory delete failed - %s", strerror(errno));
if (shmdt(bytes) < 0)
NSLog(@"[NSMutableDataShared -dealloc] shared memory detach failed - %s", strerror(errno));
bytes = 0;
length = 0;
capacity = 0;
@ -1710,8 +1729,6 @@ readContentsOfFile(NSString* path, void** buf, unsigned* len)
bytes = shmat(shmid, 0, 0);
e = errno;
shmctl(shmid, IPC_RMID, &buf); /* Mark for later deletion. */
if (bytes == (void*)-1)
{
NSLog(@"[NSMutableDataShared -initWithCapacity:] shared memory attach failed for %u - %s", bufferSize, strerror(e));
@ -1774,13 +1791,22 @@ readContentsOfFile(NSString* path, void** buf, unsigned* len)
format:@"Unable to create shared memory segment - %s.",
strerror(errno)];
tmp = shmat(newid, 0, 0);
if (shmctl(newid, IPC_RMID, &buf) == 0) /* Mark for later deletion. */
if ((int)tmp == -1) /* Attached memory? */
[NSException raise:NSMallocException
format:@"Unable to attach to shared memory segment."];
memcpy(tmp, bytes, length);
if (bytes)
shmdt(bytes);
{
struct shmid_ds buf;
if (shmctl(shmid, IPC_STAT, &buf) < 0)
NSLog(@"[NSMutableDataShared -setCapacity:] shared memory control failed - %s", strerror(errno));
else if (buf.shm_nattch == 1)
if (shmctl(shmid, IPC_RMID, &buf) < 0) /* Mark for deletion. */
NSLog(@"[NSMutableDataShared -setCapacity:] shared memory delete failed - %s", strerror(errno));
if (shmdt(bytes) < 0) /* Detach memory. */
NSLog(@"[NSMutableDataShared -setCapacity:] shared memory detach failed - %s", strerror(errno));
}
bytes = tmp;
shmid = newid;
capacity = size;

View file

@ -320,7 +320,7 @@ extraRefCount (id anObject)
if (double_release_check_enabled)
{
unsigned release_count;
unsigned retain_count = extraRefCount(self);
unsigned retain_count = [self retainCount];
release_count = [autorelease_class autoreleaseCountForObject:self];
if (release_count > retain_count)
[NSException
@ -421,9 +421,9 @@ extraRefCount (id anObject)
if (double_release_check_enabled)
{
unsigned release_count;
unsigned retain_count = extraRefCount(self);
unsigned retain_count = [self retainCount];
release_count = [autorelease_class autoreleaseCountForObject:self];
if (release_count > retain_count)
if (release_count >= retain_count)
[NSException raise: NSGenericException
format: @"Release would release object too many times."];
}
@ -458,11 +458,7 @@ extraRefCount (id anObject)
- (unsigned) retainCount
{
unsigned release_count;
unsigned retain_count = extraRefCount(self) + 1;
release_count = [autorelease_class autoreleaseCountForObject:self];
return retain_count - release_count;
return extraRefCount(self) + 1;
}
+ (unsigned) retainCount

View file

@ -39,9 +39,6 @@
+ (id) allocWithZone: (NSZone*)z
{
NSProxy* ob = (NSProxy*) NSAllocateObject (self, 0, z);
if (ob) {
[ob retain];
}
return ob;
}
@ -217,7 +214,7 @@
- (void) release
{
if (_retain_count-- == 1) {
if (_retain_count-- == 0) {
[self dealloc];
}
}
@ -247,7 +244,12 @@
- (unsigned int) retainCount
{
return _retain_count;
return _retain_count + 1;
}
+ (unsigned) retainCount
{
return UINT_MAX;
}
- self

View file

@ -1110,11 +1110,12 @@ static int debug_run_loop = 0;
}
/* Use the earlier of the two dates we have. */
d = [d earlierDate:date];
d = [[d earlierDate:date] retain];
/* Wait, listening to our input sources. */
[self acceptInputForMode: mode beforeDate: d];
[d release];
return YES;
}

View file

@ -85,13 +85,13 @@
- (oneway void) release
{
if (!_retain_count--)
if (_retain_count-- == 0)
[self dealloc];
}
- (unsigned) retainCount
{
return _retain_count;
return _retain_count + 1;
}
- (void) dealloc

View file

@ -462,7 +462,7 @@ enum
- (unsigned) retainCount
{
return _retain_count;
return _retain_count + 1;
}
- autorelease

View file

@ -63,8 +63,8 @@
#define GDOMAP 1 /* 1 = Use name server. */
#define stringify_it(X) #X
#define make_gdomap_cmd(X) stringify_it(X) "/bin/gdomap &"
#define make_gdomap_err(X) "check that " stringify_it(X) "/bin/gdomap is running and owned by root."
#define make_gdomap_cmd(X) stringify_it(X) "/Tools/gdomap &"
#define make_gdomap_err(X) "check that " stringify_it(X) "/Tools/gdomap is running and owned by root."
#endif /* !__WIN32__ */
#include <string.h> /* for memset() and strchr() */
@ -145,7 +145,7 @@ static int debug_tcp_port = 0;
/*
* Code to contact distributed objects name server.
*/
#include "gdomap.h"
#include "../Tools/gdomap.h"
extern int errno; /* For systems where it is not in the include */

File diff suppressed because it is too large Load diff

View file

@ -1,174 +0,0 @@
/* Include for communications with GNUstep Distributed Objects name server
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
Created: October 1996
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* About the GNU Distributed Objects name-server
*
* The name server is intended to work with both the UDP and the TCP
* protocols. It is intended that the TCP interface be used by
* GNUstep programs, while the UDP interface is intended primarily
* for communication between name servers on different machines.
*
* The communications protocol is identical for both TCP and UDP and
* consists of a simple request-response sequence.
*
* Each request is a single 264 byte message consisting of -
* a single byte request type,
* a single byte giving name length,
* a single byte specifying the type of port being registered
* or looked up, or a nul byte for probe operations.
* a single nul byte.
* a four byte port number in network byte order must be
* present for register operations, otherwise this is zero.
* a service name of 0 to 255 bytes (or an IP address in
* network byte order for probe operations)
* 0 to 254 nul bytes padding the service name to 255.
* a terminating nul byte.
* The total is always sent in a packet of 262 bytes with
* everything after the service name (except the final byte)
* cleared to nul bytes.
*
* Each response consists of at least 4 bytes and depends on the
* corresponding request type and where it came from as follows -
*
* Request type Effect
*
* GDO_LOOKUP Looks up the server name and returns its port number.
* Response is the port number in network byte order,
* or zero if the named server was not registered.
*
* GDO_REGISTER Registers the given server name with a port number.
* This service is only available to processes on the
* same host as the name server.
* Response is the port number in network byte order,
* or zero if the named server was already registered.
*
* GDO_UNREG Un-register the server name and return old port number.
* This service is only available to a process on the
* same host as this name server and which sent the
* request from the port associated with the name.
* Response is the old port number in network byte order,
* or zero if the name could not be un-registered.
*
* GDO_SERVERS Return a list of the known servers on the local net.
* Response is an unsigned long (in network byte order)
* saying how many servers the name server knows about,
* followed by a list of their IP addresses in network
* byte order.
* NB. This response may not be possible over UDP as the
* response length may exceed the maximum UDP packet size.
*
* The following are used for communications between name servers -
*
* GDO_PROBE Requests a response
* For a request from a name server via UDP there is no
* response, but a GDO_REPLY request is sent.
* For a request from a non-name-server, or a TCP
* connect, the response is the port number of this
* server in network byte order.
*
* GDO_PREPLY Replies to a GDO_PROBE via UDP from a name server.
* No response is sent.
*
*
* HOW IT WORKS AND WHY (implementation notes)
*
* 1. The fixed size of a request packet was chosen for maximum
* ease and speed of implementation of a non-blocking name server.
* The server knows how much it needs to read and can therefore
* usually do a read as a single operation since it doesn't have
* to read a little, figure out request length, allocate a buffer,
* and read the rest.
*
* The server name length (bytes) is specified - no assumptions
* should be made about whether the name contains nul characters
* or indeed about the name at all. This is future-proofing.
*
* 2. Why UDP as well as TCP?
* The OpenStep specification says that a connection may be
* established to any host on the local network which supplys a
* named service if the host name is specified as '*'
*
* This means that the application must poll to see if it can
* find a server with the name it wants. The polling could take
* a huge amount of time!
*
* To make this all easier - the server is capable of supplying
* a list of those hosts on the local network which it knows to
* have (or have had) a name server running on them.
*
* The application then need only poll those name servers to find
* the service it wants.
*
* However - to give the application a list of hosts, the name
* server must have got the information from somewhere.
* To gather the information the server has to poll the machines
* on the net which would take ages using TCP since attempts to
* talk to machines which are down or do not exist will take a
* while to time out.
*
* To make things speedy, the server sends out GDO_PROBE requests
* on UDP to all the machines on the net when it starts up.
* Each machine which has a name server notes that the new name
* server has started up and sends back a GDOPREPLY packet so
* that the new name server will know about it.
*
* Things are never perfect though - if a name server dies, the
* other name servers won't know, and will continute to tell
* applications that it is there.
*/
#define GDOMAP_PORT (538) /* The well-known port for name server. */
/*
* Request type codes
*/
#define GDO_REGISTER 'R'
#define GDO_LOOKUP 'L'
#define GDO_UNREG 'U'
#define GDO_SERVERS 'S'
#define GDO_PROBE 'P'
#define GDO_PREPLY 'p'
/*
* Port type codes
*/
#define GDO_TCP_GDO 'T' /* tcp/ip distributed object server. */
#define GDO_UDP_GDO 'U' /* udp/ip distributed object server. */
#define GDO_TCP_FOREIGN 't' /* tcp/ip simple socket connection. */
#define GDO_UDP_FOREIGN 'u' /* udp/ip simple socket connection. */
/*
* Structure to hold a request.
*/
typedef struct {
unsigned char rtype;
unsigned char nsize;
unsigned char ptype;
unsigned char dummy;
unsigned int port;
char name[256];
} gdo_req;
#define GDO_REQ_SIZE 264 /* The size of a request packet. */