Assert is_valid in many places.

([TcpInPort +newForReceivingFromPortNumber:]): Get the address of the
host, not localhost=127.0.0.1.
([TcpInPort -invalidate]): Remove ourselves from socket_2_port and
port_number_2_port here instead of in -dealloc.
([TcpInPort -description]): Indicate whether we are valid or not in
string.
([TcpOutPort -description]): Likewise.
([TcpOutPort -invalidate]): Assert is_valid, don't just conditionally
execute body.  Remove ourselves from out_port_bag and socket_2_port
here, not in -dealloc.
([TcpPacket +_getPacketSize:andReplyPort:fromSocket:inPort:]): If we
don't read() full prefix, don't abort(), just return EOF.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1091 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
mccallum 1996-03-07 18:14:23 +00:00
parent f6d5c1c787
commit 4e48eb0082

View file

@ -28,6 +28,7 @@
/* TODO: /* TODO:
Make the sockets non-blocking. Make the sockets non-blocking.
Change so we don't wait on incoming packet prefix. Change so we don't wait on incoming packet prefix.
All the abort()'s should be Exceptions.
*/ */
#include <objects/stdobjects.h> #include <objects/stdobjects.h>
@ -36,6 +37,8 @@
#include <objects/Notification.h> #include <objects/Notification.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> /* for gethostname() */
#include <sys/param.h> /* for MAXHOSTNAMELEN */
#ifndef WIN32 #ifndef WIN32
#include <sys/time.h> #include <sys/time.h>
@ -157,7 +160,10 @@ static NSMapTable* port_number_2_port;
/* If there already is a TcpInPort listening to this port number, /* If there already is a TcpInPort listening to this port number,
don't create a new one, just return the old one. */ don't create a new one, just return the old one. */
if ((p = (id) NSMapGet (port_number_2_port, (void*)((int)n)))) if ((p = (id) NSMapGet (port_number_2_port, (void*)((int)n))))
return p; {
assert (p->is_valid);
return p;
}
/* There isn't already a TcpInPort for this port number, so create /* There isn't already a TcpInPort for this port number, so create
a new one. */ a new one. */
@ -169,7 +175,7 @@ static NSMapTable* port_number_2_port;
p->_socket = socket (AF_INET, SOCK_STREAM, 0); p->_socket = socket (AF_INET, SOCK_STREAM, 0);
if (p->_socket < 0) if (p->_socket < 0)
{ {
perror ("[TcpInPort +newForReceivingFromPortNumber] socket()"); perror ("[TcpInPort +newForReceivingFromPortNumber:] socket()");
abort (); abort ();
} }
@ -180,10 +186,23 @@ static NSMapTable* port_number_2_port;
/* Give the socket a name using bind(). */ /* Give the socket a name using bind(). */
{ {
struct hostent *hp; struct hostent *hp;
hp = gethostbyname ("localhost"); // xxx No! Not "localhost" the host name char hostname[MAXHOSTNAMELEN];
/* Use localhost's address, and not INADDR_ANY, so that went we int len = MAXHOSTNAMELEN;
if (gethostname (hostname, len) < 0)
{
perror ("[TcpInPort +newForReceivingFromPortNumber:] gethostname()");
abort ();
}
hp = gethostbyname (hostname);
if (!hp)
/* xxx This won't work with port connections on a network, though.
Fix this. Perhaps there is a better way of getting the address
of the local host. */
hp = gethostbyname ("localhost");
assert (hp);
/* Use host's address, and not INADDR_ANY, so that went we
encode our _listening_address for a D.O. operation, they get encode our _listening_address for a D.O. operation, they get
our unique host address. */ our unique host address that can identify us across the network. */
memcpy (&(p->_listening_address.sin_addr), hp->h_addr, hp->h_length); memcpy (&(p->_listening_address.sin_addr), hp->h_addr, hp->h_length);
p->_listening_address.sin_family = AF_INET; p->_listening_address.sin_family = AF_INET;
p->_listening_address.sin_port = htons (n); p->_listening_address.sin_port = htons (n);
@ -274,6 +293,7 @@ static NSMapTable* port_number_2_port;
- (struct sockaddr_in*) _listeningSockaddr - (struct sockaddr_in*) _listeningSockaddr
{ {
assert (is_valid);
return &_listening_address; return &_listening_address;
} }
@ -286,6 +306,8 @@ static NSMapTable* port_number_2_port;
void *select_timeout; void *select_timeout;
int sel_ret; int sel_ret;
assert (is_valid);
/* If MILLISECONDS is less than 0, wait forever. */ /* If MILLISECONDS is less than 0, wait forever. */
if (milliseconds >= 0) if (milliseconds >= 0)
{ {
@ -388,10 +410,12 @@ static NSMapTable* port_number_2_port;
{ {
/* We got an EOF when trying to read packet data; /* We got an EOF when trying to read packet data;
release the packet and invalidate the corresponding release the packet and invalidate the corresponding
port. */ port, and keep on waiting for incoming data on
other sockets. */
[packet release]; [packet release];
[(id) NSMapGet (client_sock_2_out_port, (void*)fd_index) [(id) NSMapGet (client_sock_2_out_port, (void*)fd_index)
invalidate]; invalidate];
continue;
} }
else if (remaining == 0) else if (remaining == 0)
/* No bytes are remaining to be read for this packet; /* No bytes are remaining to be read for this packet;
@ -407,6 +431,7 @@ static NSMapTable* port_number_2_port;
{ {
int s = [p _socket]; int s = [p _socket];
assert (is_valid);
/* Make sure it hasn't already been added. */ /* Make sure it hasn't already been added. */
assert (!NSMapGet (client_sock_2_out_port, (void*)s)); assert (!NSMapGet (client_sock_2_out_port, (void*)s));
@ -421,6 +446,7 @@ static NSMapTable* port_number_2_port;
id packet; id packet;
int s = [p _socket]; int s = [p _socket];
assert (is_valid);
if (debug_tcp_port) if (debug_tcp_port)
fprintf (stderr, fprintf (stderr,
"%s: Closed connection from\n %s\n", "%s: Closed connection from\n %s\n",
@ -478,6 +504,12 @@ static NSMapTable* port_number_2_port;
close (_socket); close (_socket);
/* These are here, and not in -dealloc, to prevent
+newForReceivingFromPortNumber from returning invalid sockets. */
NSMapRemove (socket_2_port, (void*)_socket);
NSMapRemove (port_number_2_port,
(void*)(int) ntohs(_listening_address.sin_port));
/* This also posts a PortBecameInvalidNotification. */ /* This also posts a PortBecameInvalidNotification. */
[super invalidate]; [super invalidate];
} }
@ -486,12 +518,9 @@ static NSMapTable* port_number_2_port;
- (void) dealloc - (void) dealloc
{ {
[self invalidate]; [self invalidate];
NSMapRemove (port_number_2_port,
(void*)(int) ntohs(_listening_address.sin_port));
/* assert that these are empty? */ /* assert that these are empty? */
NSFreeMapTable (client_sock_2_out_port); NSFreeMapTable (client_sock_2_out_port);
NSFreeMapTable (client_sock_2_packet); NSFreeMapTable (client_sock_2_packet);
NSMapRemove (socket_2_port, (void*)_socket);
[super dealloc]; [super dealloc];
} }
@ -513,8 +542,9 @@ static NSMapTable* port_number_2_port;
- description - description
{ {
return [NSString return [NSString
stringWithFormat: @"%s 0x%x port %hd socket %d", stringWithFormat: @"%s%c0x%x port %hd socket %d",
object_get_class_name (self), object_get_class_name (self),
is_valid ? ' ' : '-',
(unsigned)self, (unsigned)self,
ntohs (_listening_address.sin_port), ntohs (_listening_address.sin_port),
_socket]; _socket];
@ -529,6 +559,7 @@ static NSMapTable* port_number_2_port;
- (void) encodeWithCoder: aCoder - (void) encodeWithCoder: aCoder
{ {
assert (is_valid);
/* We are actually encoding a "send right" (ala Mach), /* We are actually encoding a "send right" (ala Mach),
not a receive right. not a receive right.
These values must match those expected by [TcpOutPort +newWithCoder] */ These values must match those expected by [TcpOutPort +newWithCoder] */
@ -618,13 +649,16 @@ static NSMapTable *out_port_bag = NULL;
{ {
/* xxx Do I need to make sure connectedInPort is the same too? */ /* xxx Do I need to make sure connectedInPort is the same too? */
/* xxx Come up with a way to do this with a hash key, not a list. */ /* xxx Come up with a way to do this with a hash key, not a list. */
if ((sockaddr->sin_port if ((sockaddr->sin_port
== p->_remote_in_port_address.sin_port) == p->_remote_in_port_address.sin_port)
&& (sockaddr->sin_addr.s_addr && (sockaddr->sin_addr.s_addr
== p->_remote_in_port_address.sin_addr.s_addr)) == p->_remote_in_port_address.sin_addr.s_addr))
/* Assume that sin_family is equal. Using memcmp() doesn't /* Assume that sin_family is equal. Using memcmp() doesn't
work because sin_zero's may differ. */ work because sin_zero's may differ. */
return p; {
assert (p->is_valid);
return p;
}
} }
} }
/* xxx When the AcceptedSocket-style OutPort get's it's /* xxx When the AcceptedSocket-style OutPort get's it's
@ -662,6 +696,7 @@ static NSMapTable *out_port_bag = NULL;
sizeof (p->_remote_in_port_address)); sizeof (p->_remote_in_port_address));
} }
} }
assert (p->is_valid);
return p; return p;
} }
@ -692,9 +727,14 @@ static NSMapTable *out_port_bag = NULL;
assert (sockaddr->sin_port); assert (sockaddr->sin_port);
memcpy (&(p->_remote_in_port_address), sockaddr, sizeof(*sockaddr)); memcpy (&(p->_remote_in_port_address), sockaddr, sizeof(*sockaddr));
} }
/* Else, _remote_in_port_address will remain as zero's for the else
time being, and may get set later by calling +newForSendingToSockaddr.. {
with a non-zero socket, and a non-NULL sockaddr. */ /* Else, _remote_in_port_address will remain as zero's for the
time being, and may get set later by calling
+newForSendingToSockaddr.. with a non-zero socket, and a
non-NULL sockaddr. */
p->_remote_in_port_address.sin_family = 0;
}
/* xxx Do I need to bind(_socket) to this address? I don't think so. */ /* xxx Do I need to bind(_socket) to this address? I don't think so. */
@ -793,6 +833,8 @@ static NSMapTable *out_port_bag = NULL;
int c, l; int c, l;
id reply_port = [packet replyPort]; id reply_port = [packet replyPort];
assert (is_valid);
/* If the socket of this TcpOutPort isn't already being polled /* If the socket of this TcpOutPort isn't already being polled
for incoming data by a TcpInPort, and if the packet's REPLY_PORT for incoming data by a TcpInPort, and if the packet's REPLY_PORT
is non-nil, then set up this TcpOutPort's socket to be polled by is non-nil, then set up this TcpOutPort's socket to be polled by
@ -842,32 +884,34 @@ static NSMapTable *out_port_bag = NULL;
- (void) invalidate - (void) invalidate
{ {
if (is_valid) assert (is_valid);
{
if (close (_socket) < 0)
{
perror ("[TcpOutPort -invalidate] close()");
abort ();
}
[_polling_in_port _connectedOutPortInvalidated: self];
[_polling_in_port release];
_polling_in_port = nil;
/* This is here, and not in -dealloc, because invalidated
but not dealloc'ed ports should not be returned from
the out_port_bag in +newForSendingToSockaddr:... */
NSMapRemove (out_port_bag, (void*)self);
/* This also posts a PortBecameInvalidNotification. */ if (close (_socket) < 0)
[super invalidate]; {
perror ("[TcpOutPort -invalidate] close()");
abort ();
} }
[_polling_in_port _connectedOutPortInvalidated: self];
[_polling_in_port release];
_polling_in_port = nil;
/* This is here, and not in -dealloc, because invalidated
but not dealloc'ed ports should not be returned from
the out_port_bag in +newForSendingToSockaddr:... */
NSMapRemove (out_port_bag, (void*)self);
/* This is here, and not in -dealloc, because invalidated
but not dealloc'ed ports should not be returned from
the socket_2_port in +newForSendingToSockaddr:... */
NSMapRemove (socket_2_port, (void*)_socket);
/* This also posts a PortBecameInvalidNotification. */
[super invalidate];
} }
- (void) dealloc - (void) dealloc
{ {
if (is_valid) if (is_valid)
[self invalidate]; [self invalidate];
NSMapRemove (socket_2_port, (void*)_socket);
[super dealloc]; [super dealloc];
} }
@ -891,8 +935,9 @@ static NSMapTable *out_port_bag = NULL;
- description - description
{ {
return [NSString return [NSString
stringWithFormat: @"%s 0x%x host %s port %hd socket %d", stringWithFormat: @"%s%c0x%x host %s port %hd socket %d",
object_get_class_name (self), object_get_class_name (self),
is_valid ? ' ' : '-',
(unsigned)self, (unsigned)self,
inet_ntoa (_remote_in_port_address.sin_addr), inet_ntoa (_remote_in_port_address.sin_addr),
ntohs (_remote_in_port_address.sin_port), ntohs (_remote_in_port_address.sin_port),
@ -901,16 +946,17 @@ static NSMapTable *out_port_bag = NULL;
- (void) encodeWithCoder: aCoder - (void) encodeWithCoder: aCoder
{ {
assert (is_valid);
[super encodeWithCoder: aCoder]; [super encodeWithCoder: aCoder];
assert (!_polling_in_port assert (!_polling_in_port
|| (ntohs (_remote_in_port_address.sin_port) || (ntohs (_remote_in_port_address.sin_port)
!= [_polling_in_port portNumber])); != [_polling_in_port portNumber]));
[aCoder encodeValueOfCType: @encode(typeof(_remote_in_port_address.sin_port)) [aCoder encodeValueOfCType: @encode(typeof(_remote_in_port_address.sin_port))
at: &_remote_in_port_address.sin_port at: &(_remote_in_port_address.sin_port)
withName: @"socket number"]; withName: @"socket number"];
[aCoder encodeValueOfCType: [aCoder encodeValueOfCType:
@encode(typeof(_remote_in_port_address.sin_addr.s_addr)) @encode(typeof(_remote_in_port_address.sin_addr.s_addr))
at: &_remote_in_port_address.sin_addr.s_addr at: &(_remote_in_port_address.sin_addr.s_addr)
withName: @"inet address"]; withName: @"inet address"];
} }
@ -920,10 +966,10 @@ static NSMapTable *out_port_bag = NULL;
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
[aCoder decodeValueOfCType: @encode(typeof(addr.sin_port)) [aCoder decodeValueOfCType: @encode(typeof(addr.sin_port))
at: &addr.sin_port at: &(addr.sin_port)
withName: NULL]; withName: NULL];
[aCoder decodeValueOfCType: @encode(typeof(addr.sin_addr.s_addr)) [aCoder decodeValueOfCType: @encode(typeof(addr.sin_addr.s_addr))
at: &addr.sin_addr.s_addr at: &(addr.sin_addr.s_addr)
withName: NULL]; withName: NULL];
return [TcpOutPort newForSendingToSockaddr: &addr return [TcpOutPort newForSendingToSockaddr: &addr
withAcceptedSocket: 0 withAcceptedSocket: 0
@ -967,6 +1013,7 @@ static NSMapTable *out_port_bag = NULL;
eofPosition: 0 eofPosition: 0
prefix: PREFIX_SIZE prefix: PREFIX_SIZE
position: 0]; position: 0];
assert ([p isValid]);
reply_port = p; reply_port = p;
return self; return self;
} }
@ -1012,11 +1059,19 @@ static NSMapTable *out_port_bag = NULL;
c = read (s, prefix_buffer, PREFIX_SIZE); c = read (s, prefix_buffer, PREFIX_SIZE);
if (c == 0) if (c == 0)
{ {
*packet_size = EOF; *packet_size = EOF; *rp = nil;
return; return;
} }
if (c != PREFIX_SIZE) if (c != PREFIX_SIZE)
[self error: "Failed to get packet prefix from socket."]; {
/* Was: [self error: "Failed to get packet prefix from socket."]; */
/* xxx Currently treating this the same as EOF, but perhaps
we should treat it differently. */
fprintf (stderr, "[%s %s]: Got %d chars instead of full prefix\n",
class_get_class_name (self), sel_get_name (_cmd));
*packet_size = EOF; *rp = nil;
return;
}
/* *size is the number of bytes in the packet, not including /* *size is the number of bytes in the packet, not including
the PREFIX_SIZE-byte header. */ the PREFIX_SIZE-byte header. */