mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-11 08:40:44 +00:00
New file.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1022 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
65fd114c58
commit
87e9935a0b
6 changed files with 1325 additions and 0 deletions
76
Headers/gnustep/base/TcpPort.h
Normal file
76
Headers/gnustep/base/TcpPort.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
/* Interface for stream based on TCP sockets
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: February 1996
|
||||
|
||||
This file is part of the GNU Objective C Class 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.
|
||||
*/
|
||||
|
||||
#ifndef __TcpPort_h__OBJECTS_INCLUDE
|
||||
#define __TcpPort_h__OBJECTS_INCLUDE
|
||||
|
||||
#include <objects/stdobjects.h>
|
||||
#include <objects/Port.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <Foundation/NSMapTable.h>
|
||||
|
||||
@interface TcpPacket : Packet
|
||||
@end
|
||||
|
||||
@interface TcpInPort : InPort
|
||||
{
|
||||
int _socket;
|
||||
struct sockaddr_in _address;
|
||||
fd_set active_fd_set;
|
||||
NSMapTable *client_sock_2_out_port;
|
||||
NSMapTable *client_sock_2_packet;
|
||||
}
|
||||
|
||||
+ newForReceivingFromPortNumber: (unsigned short)n;
|
||||
+ newForReceivingFromRegisteredName: (id <String>)name;
|
||||
|
||||
/* Get a packet from the net and return it. If no packet is received
|
||||
within MILLISECONDS, then return nil. The caller is responsible
|
||||
for releasing the packet. */
|
||||
- receivePacketWithTimeout: (int)milliseconds;
|
||||
|
||||
- (id <Collecting>) connectedOutPorts;
|
||||
|
||||
- (void) checkConnection;
|
||||
|
||||
@end
|
||||
|
||||
@interface TcpOutPort : OutPort
|
||||
{
|
||||
int _socket;
|
||||
struct sockaddr_in _address;
|
||||
id connected_in_port;
|
||||
}
|
||||
|
||||
+ newForSendingToPortNumber: (unsigned short)n
|
||||
onHost: (id <String>)hostname;
|
||||
+ newForSendingToRegisteredName: (id <String>)name
|
||||
onHost: (id <String>)hostname;
|
||||
- (BOOL) sendPacket: packet withTimeout: (int)milliseconds;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __TcpPort_h__OBJECTS_INCLUDE */
|
||||
|
59
Headers/gnustep/base/UdpPort.h
Normal file
59
Headers/gnustep/base/UdpPort.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* Interface for socket-based port object for use with Connection
|
||||
Copyright (C) 1994, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: July 1994
|
||||
|
||||
This file is part of the GNU Objective C Class 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.
|
||||
*/
|
||||
|
||||
#ifndef __SocketPort_h_INCLUDE_GNU
|
||||
#define __SocketPort_h_INCLUDE_GNU
|
||||
|
||||
#include <objects/stdobjects.h>
|
||||
#include <objects/Port.h>
|
||||
#include <sys/types.h>
|
||||
#ifndef WIN32
|
||||
# include <sys/socket.h>
|
||||
# include <netinet/in.h>
|
||||
#endif /* !WIN32 */
|
||||
|
||||
@interface UdpInPort : InPort
|
||||
{
|
||||
int _socket;
|
||||
struct sockaddr_in _address;
|
||||
}
|
||||
|
||||
- (int) portNumber;
|
||||
- (int) socket;
|
||||
|
||||
@end
|
||||
|
||||
@interface UdpOutPort : OutPort
|
||||
{
|
||||
struct sockaddr_in _address;
|
||||
}
|
||||
|
||||
- (int) portNumber;
|
||||
- (id <String>) hostname;
|
||||
|
||||
@end
|
||||
|
||||
@interface UdpPacket : Packet
|
||||
@end
|
||||
|
||||
#endif /* __SocketPort_h_INCLUDE_GNU */
|
632
Source/TcpPort.m
Normal file
632
Source/TcpPort.m
Normal file
|
@ -0,0 +1,632 @@
|
|||
/* Implementation of network port object based on TCP sockets
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: February 1996
|
||||
|
||||
This file is part of the GNU Objective C Class 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.
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
Make the sockets non-blocking.
|
||||
*/
|
||||
|
||||
#include <objects/stdobjects.h>
|
||||
#include <objects/TcpPort.h>
|
||||
#include <objects/Array.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#define debug_tcp_port 1
|
||||
|
||||
@interface TcpInPort (Private)
|
||||
- (int) _socket;
|
||||
- (void) _addOutPort: p;
|
||||
- (void) _connectedOutPortInvalidated: p;
|
||||
@end
|
||||
|
||||
@interface TcpOutPort (Private)
|
||||
- (int) _socket;
|
||||
- _initWithSocket: (int)s inPort: ip;
|
||||
+ newWithAcceptedSocket: (int)s inPort: p;
|
||||
@end
|
||||
|
||||
@interface TcpPacket (Private)
|
||||
- (int) _fillFromSocket: (int)s;
|
||||
- (void) _writeToSocket: (int)s;
|
||||
+ (int) readPacketSizeFromSocket: (int)s;
|
||||
- _initForReceivingWithSize: (int)s replyPort: p;
|
||||
@end
|
||||
|
||||
|
||||
/* Our current, sad excuse for a name server. */
|
||||
|
||||
static unsigned short
|
||||
name_2_port_number (const char *name)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
unsigned int ctr = 0;
|
||||
|
||||
while (*name)
|
||||
{
|
||||
ret ^= *name++ << ctr;
|
||||
ctr = (ctr + 1) % sizeof (void *);
|
||||
}
|
||||
return (ret % (65535 - IPPORT_USERRESERVED - 1)) + IPPORT_USERRESERVED;
|
||||
/* return strlen (name) + IPPORT_USERRESERVED; */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Both TcpInPort's and TcpOutPort's are entered in this maptable. */
|
||||
|
||||
static NSMapTable *socket_2_port;
|
||||
static void
|
||||
init_socket_2_port ()
|
||||
{
|
||||
socket_2_port =
|
||||
NSCreateMapTable (NSIntMapKeyCallBacks,
|
||||
NSNonOwnedPointerMapValueCallBacks, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@implementation TcpInPort
|
||||
|
||||
static NSMapTable* port_number_2_port;
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [TcpInPort class])
|
||||
port_number_2_port =
|
||||
NSCreateMapTable (NSIntMapKeyCallBacks,
|
||||
NSNonOwnedPointerMapValueCallBacks, 0);
|
||||
if (!socket_2_port)
|
||||
init_socket_2_port ();
|
||||
}
|
||||
|
||||
/* this is the designated initializer. */
|
||||
+ newForReceivingFromPortNumber: (unsigned short)n
|
||||
{
|
||||
TcpInPort *p;
|
||||
int sock;
|
||||
|
||||
if ((p = (id) NSMapGet (port_number_2_port, (void*)((int)n))))
|
||||
return p;
|
||||
|
||||
/* Create the socket. */
|
||||
sock = socket (AF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0)
|
||||
{
|
||||
perror ("socket");
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* Create the port object. */
|
||||
p = [[TcpInPort alloc] init];
|
||||
p->_socket = sock;
|
||||
NSMapInsert (socket_2_port, (void*)sock, self);
|
||||
|
||||
/* Give the socket a name. */
|
||||
p->_address.sin_family = AF_INET;
|
||||
p->_address.sin_addr.s_addr = htonl (INADDR_ANY);
|
||||
p->_address.sin_port = htons (n);
|
||||
if (bind (sock, (struct sockaddr*) &(p->_address), sizeof (p->_address)) < 0)
|
||||
{
|
||||
perror ("bind");
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* Set it up to accept connections, let 10 pending connections queue */
|
||||
if (listen (sock, 10) < 0)
|
||||
{
|
||||
perror ("listen");
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* Initialize the set of active sockets. */
|
||||
FD_ZERO (&(p->active_fd_set));
|
||||
FD_SET (sock, &(p->active_fd_set));
|
||||
|
||||
/* Initializer the tables. */
|
||||
p->client_sock_2_out_port =
|
||||
NSCreateMapTable (NSIntMapKeyCallBacks,
|
||||
NSNonOwnedPointerMapValueCallBacks, 0);
|
||||
p->client_sock_2_packet =
|
||||
NSCreateMapTable (NSIntMapKeyCallBacks,
|
||||
NSNonOwnedPointerMapValueCallBacks, 0);
|
||||
|
||||
/* Record the new port in the table. */
|
||||
NSMapInsert (port_number_2_port, (void*)(int)n, p);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
+ newForReceivingFromRegisteredName: (id <String>)name
|
||||
{
|
||||
return [self newForReceivingFromPortNumber:
|
||||
name_2_port_number ([name cStringNoCopy])];
|
||||
}
|
||||
|
||||
+ newForReceiving
|
||||
{
|
||||
return [self newForReceivingFromPortNumber: 0];
|
||||
}
|
||||
|
||||
- (id <Collecting>) connectedOutPorts
|
||||
{
|
||||
NSMapEnumerator me = NSEnumerateMapTable (client_sock_2_out_port);
|
||||
int count = NSCountMapTable (client_sock_2_out_port);
|
||||
int sock;
|
||||
id out_port;
|
||||
id out_ports[count];
|
||||
int i;
|
||||
for (i = 0;
|
||||
NSNextMapEnumeratorPair (&me, (void*)&sock, (void*)&out_port);
|
||||
i++)
|
||||
out_ports[i] = out_port;
|
||||
return [[[Array alloc] initWithObjects: out_ports count: count]
|
||||
autorelease];
|
||||
}
|
||||
|
||||
- receivePacketWithTimeout: (int)milliseconds
|
||||
{
|
||||
static int fd_index = 0;
|
||||
fd_set read_fd_set;
|
||||
struct sockaddr_in clientname;
|
||||
struct timeval timeout;
|
||||
void *select_timeout;
|
||||
int sel_ret;
|
||||
|
||||
/* If MILLISECONDS is less than 0, wait forever. */
|
||||
if (milliseconds >= 0)
|
||||
{
|
||||
timeout.tv_sec = milliseconds / 1000;
|
||||
timeout.tv_usec = (milliseconds % 1000) * 1000;
|
||||
select_timeout = &timeout;
|
||||
}
|
||||
else
|
||||
select_timeout = NULL;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
read_fd_set = active_fd_set;
|
||||
sel_ret = select (FD_SETSIZE, &read_fd_set, NULL, NULL, select_timeout);
|
||||
if (sel_ret < 0)
|
||||
{
|
||||
perror ("select");
|
||||
abort ();
|
||||
}
|
||||
else if (sel_ret == 0)
|
||||
return nil;
|
||||
|
||||
for (fd_index = 0; fd_index < FD_SETSIZE; fd_index++)
|
||||
if (FD_ISSET (fd_index, &read_fd_set))
|
||||
{
|
||||
if (fd_index == _socket)
|
||||
{
|
||||
/* This is a connection request on the original socket. */
|
||||
int new;
|
||||
int size;
|
||||
|
||||
size = sizeof (clientname);
|
||||
new = accept (_socket, (struct sockaddr*)&clientname, &size);
|
||||
if (new < 0)
|
||||
{
|
||||
perror ("accept");
|
||||
abort ();
|
||||
}
|
||||
if (debug_tcp_port)
|
||||
fprintf (stderr,
|
||||
"Accepted connection from host %s, port %hd.\n",
|
||||
inet_ntoa (clientname.sin_addr),
|
||||
ntohs (clientname.sin_port));
|
||||
[self _addOutPort: [TcpOutPort newWithAcceptedSocket: new
|
||||
inPort: self]];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Data arriving on an already-connected socket. */
|
||||
TcpPacket *packet;
|
||||
int remaining;
|
||||
if (!(packet = NSMapGet (client_sock_2_packet,
|
||||
(void*)fd_index)))
|
||||
{
|
||||
/* This is the beginning of a new packet on this socket.
|
||||
Create a new Packet object for gathering the data. */
|
||||
|
||||
/* First, get the packet size, (which is encoded in
|
||||
the first few bytes of the stream). */
|
||||
int packet_size =
|
||||
[TcpPacket readPacketSizeFromSocket: fd_index];
|
||||
/* We got an EOF when trying to read the packet size;
|
||||
invalidate the port, and keep on waiting for
|
||||
incoming data on other sockets. */
|
||||
if (packet_size == EOF)
|
||||
{
|
||||
[(id) NSMapGet (client_sock_2_out_port,
|
||||
(void*)fd_index)
|
||||
invalidate];
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet = [[TcpPacket alloc]
|
||||
_initForReceivingWithSize: packet_size
|
||||
replyPort:
|
||||
NSMapGet (client_sock_2_out_port,
|
||||
(void*)fd_index)];
|
||||
}
|
||||
/* The packet has now been created with correct capacity */
|
||||
}
|
||||
|
||||
/* Suck bytes from the socket into the packet; find out
|
||||
how many more bytes are needed before packet will be
|
||||
complete. */
|
||||
remaining = [packet _fillFromSocket: (int)fd_index];
|
||||
if (remaining == EOF)
|
||||
{
|
||||
/* We got an EOF when trying to read packet data;
|
||||
release the packet and invalidate the corresponding
|
||||
port. */
|
||||
[packet release];
|
||||
[(id) NSMapGet (client_sock_2_out_port, (void*)fd_index)
|
||||
invalidate];
|
||||
}
|
||||
else if (remaining == 0)
|
||||
/* No bytes are remaining to be read for this packet;
|
||||
the packet is complete; return it. */
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void) _addOutPort: p
|
||||
{
|
||||
int s = [p _socket];
|
||||
|
||||
FD_SET (s, &active_fd_set);
|
||||
|
||||
NSMapInsert (client_sock_2_out_port, (void*)s, p);
|
||||
}
|
||||
|
||||
- (void) _connectedOutPortInvalidated: p
|
||||
{
|
||||
id packet;
|
||||
int s = [p _socket];
|
||||
|
||||
packet = NSMapGet (client_sock_2_packet, (void*)s);
|
||||
if (packet)
|
||||
{
|
||||
NSMapRemove (client_sock_2_packet, (void*)s);
|
||||
[packet release];
|
||||
}
|
||||
NSMapRemove (client_sock_2_out_port, (void*)s);
|
||||
FD_CLR(s, &active_fd_set);
|
||||
}
|
||||
|
||||
- (int) _socket
|
||||
{
|
||||
return _socket;
|
||||
}
|
||||
|
||||
- (void) invalidate
|
||||
{
|
||||
if (is_valid)
|
||||
{
|
||||
NSMapEnumerator me = NSEnumerateMapTable (client_sock_2_out_port);
|
||||
int count = NSCountMapTable (client_sock_2_out_port);
|
||||
id out_port;
|
||||
int sock;
|
||||
id out_ports[count];
|
||||
int i;
|
||||
for (i = 0;
|
||||
NSNextMapEnumeratorPair (&me, (void*)&sock, (void*)&out_port);
|
||||
i++)
|
||||
out_ports[i] = out_port;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
/* This will call [self _invalidateConnectedOutPort: for each. */
|
||||
[out_ports[i] invalidate];
|
||||
}
|
||||
assert (!NSCountMapTable (client_sock_2_out_port));
|
||||
close (_socket);
|
||||
[super invalidate];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[self invalidate];
|
||||
NSMapRemove (port_number_2_port, (void*)(int)ntohs(_address.sin_port));
|
||||
/* assert that these are empty? */
|
||||
NSFreeMapTable (client_sock_2_out_port);
|
||||
NSFreeMapTable (client_sock_2_packet);
|
||||
NSMapRemove (socket_2_port, (void*)_socket);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) checkConnection
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
}
|
||||
|
||||
- classForConnectedCoder: aRmc
|
||||
{
|
||||
/* Make sure that Connection's always send us bycopy,
|
||||
i.e. as our own class, not a Proxy class. */
|
||||
return [self class];
|
||||
}
|
||||
|
||||
- (Class) packetClass
|
||||
{
|
||||
return [TcpPacket class];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation TcpOutPort
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [TcpOutPort class])
|
||||
{
|
||||
if (!socket_2_port)
|
||||
init_socket_2_port ();
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the designated initializer. */
|
||||
- _initWithSocket: (int)s inPort: ip
|
||||
{
|
||||
[super init];
|
||||
_socket = s;
|
||||
NSMapInsert (socket_2_port, (void*)s, self);
|
||||
connected_in_port = ip;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ newForSendingToPortNumber: (unsigned short)n
|
||||
onHost: (id <String>)hostname
|
||||
{
|
||||
TcpOutPort *p;
|
||||
int s;
|
||||
|
||||
/* xxx If the TcpOutPort object already exists, just return it. */
|
||||
/* This needs to be judged according to the port number and host;
|
||||
this is what will get sent when a TcpPort encodes itself. */
|
||||
|
||||
/* There isn't one already; create the TcpOutPort. */
|
||||
|
||||
/* Create the socket. */
|
||||
s = socket (AF_INET, SOCK_STREAM, 0);
|
||||
if (s < 0)
|
||||
{
|
||||
perror ("socket (client)");
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* Create a port object. */
|
||||
p = [[self alloc] _initWithSocket: s inPort: nil];
|
||||
|
||||
/* Initialize the address. */
|
||||
{
|
||||
struct hostent *hostinfo;
|
||||
p->_address.sin_family = AF_INET;
|
||||
p->_address.sin_port = htons (n);
|
||||
hostinfo = gethostbyname ([hostname cStringNoCopy]);
|
||||
if (hostinfo == NULL)
|
||||
{
|
||||
fprintf (stderr, "Unknown host %s.\n", hostname);
|
||||
abort ();
|
||||
}
|
||||
p->_address.sin_addr = *(struct in_addr *) hostinfo->h_addr;
|
||||
}
|
||||
|
||||
/* Connect to destination. */
|
||||
if (connect (s, (struct sockaddr*)&(p->_address), sizeof(p->_address)) < 0)
|
||||
{
|
||||
perror ("connect (client)");
|
||||
abort ();
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
+ newForSendingToRegisteredName: (id <String>)name
|
||||
onHost: (id <String>)hostname
|
||||
{
|
||||
return [self newForSendingToPortNumber:
|
||||
name_2_port_number ([name cStringNoCopy])
|
||||
onHost: hostname];;
|
||||
}
|
||||
|
||||
+ newWithAcceptedSocket: (int)s inPort: p
|
||||
{
|
||||
return [[self alloc] _initWithSocket: s inPort: p];
|
||||
}
|
||||
|
||||
- (int) writeBytes: (const char*)b length: (int)len
|
||||
{
|
||||
return write (_socket, b, len);
|
||||
}
|
||||
|
||||
- (BOOL) sendPacket: packet withTimeout: (int)milliseconds
|
||||
{
|
||||
int c, l;
|
||||
id reply_port = [packet replyPort];
|
||||
|
||||
if (connected_in_port == nil && reply_port != nil)
|
||||
{
|
||||
connected_in_port = reply_port;
|
||||
[connected_in_port retain];
|
||||
[connected_in_port _addOutPort: self];
|
||||
/* xxx Register socket with the replyPort. */
|
||||
}
|
||||
else if (connected_in_port != reply_port)
|
||||
[self error:"TcpPort can't change reply port of an out port once set."];
|
||||
|
||||
[packet _writeToSocket: _socket];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (int) _socket
|
||||
{
|
||||
return _socket;
|
||||
}
|
||||
|
||||
- (void) close
|
||||
{
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
- (void) invalidate
|
||||
{
|
||||
if (is_valid)
|
||||
{
|
||||
if (close (_socket) < 0)
|
||||
perror ("close, -invalidate");
|
||||
[connected_in_port _connectedOutPortInvalidated: self];
|
||||
[connected_in_port release];
|
||||
connected_in_port = nil;
|
||||
[super invalidate];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if (is_valid)
|
||||
[self invalidate];
|
||||
NSMapRemove (socket_2_port, (void*)_socket);
|
||||
}
|
||||
|
||||
- classForConnectedCoder: aRmc
|
||||
{
|
||||
/* Make sure that Connection's always send us bycopy,
|
||||
i.e. as our own class, not a Proxy class. */
|
||||
return [self class];
|
||||
}
|
||||
|
||||
- (Class) packetClass
|
||||
{
|
||||
return [TcpPacket class];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation TcpPacket
|
||||
|
||||
/* If you change this, you must change the use of ntohs() and htons() below. */
|
||||
#define PREFIX_TYPE unsigned short
|
||||
#define PREFIX_LENGTH sizeof (PREFIX_TYPE)
|
||||
|
||||
/* This is the designated initialzer. */
|
||||
/* xxx This will change; it doesn't set it's buffer size with a nice
|
||||
interface */
|
||||
- _initForReceivingWithSize: (int)s replyPort: p
|
||||
{
|
||||
[super _initOnMallocBuffer: (*objc_malloc) (s)
|
||||
size: s
|
||||
eofPosition: 0
|
||||
prefix: PREFIX_LENGTH
|
||||
position: 0];
|
||||
assert (p);
|
||||
reply_port = p;
|
||||
return self;
|
||||
}
|
||||
|
||||
- initForSendingWithCapacity: (unsigned)c
|
||||
replyPort: p
|
||||
{
|
||||
[super _initOnMallocBuffer: (*objc_malloc)(c)
|
||||
size: c
|
||||
eofPosition: 0
|
||||
prefix: PREFIX_LENGTH
|
||||
position: 0];
|
||||
reply_port = p;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) _writeToSocket: (int)s
|
||||
{
|
||||
int write_len = eofPosition + 1;
|
||||
int c, len = write_len - sizeof (unsigned short);
|
||||
|
||||
/* Put the packet size in the first two bytes of the packet.
|
||||
We use `-sizeof()' because the size does not include this
|
||||
length-indicating prefix. */
|
||||
assert (prefix == PREFIX_LENGTH);
|
||||
*(PREFIX_TYPE*)buffer = htons (len);
|
||||
|
||||
/* Write the packet on the socket. */
|
||||
c = write (s, buffer, write_len);
|
||||
if (c < 0)
|
||||
{
|
||||
perror ("write");
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* Did we sucessfully write it all? */
|
||||
if (c != write_len)
|
||||
[self error: "socket write failed"];
|
||||
}
|
||||
|
||||
+ (int) readPacketSizeFromSocket: (int)s
|
||||
{
|
||||
char size_buffer[PREFIX_LENGTH];
|
||||
int c;
|
||||
int packet_size;
|
||||
|
||||
c = read (s, size_buffer, PREFIX_LENGTH);
|
||||
if (c == 0)
|
||||
return EOF;
|
||||
if (c != PREFIX_LENGTH)
|
||||
[self error: "Failed to get packet size from socket."];
|
||||
|
||||
/* packet_size is the number of bytes in the packet, not including
|
||||
this two-byte length header. */
|
||||
packet_size = ntohs (*(PREFIX_TYPE*) size_buffer);
|
||||
assert (packet_size);
|
||||
return packet_size;
|
||||
}
|
||||
|
||||
- (int) _fillFromSocket: (int)s
|
||||
{
|
||||
int c;
|
||||
int remaining;
|
||||
|
||||
remaining = size - position;
|
||||
c = read (s, buffer + position, remaining);
|
||||
if (c == 0)
|
||||
return EOF;
|
||||
position += c;
|
||||
eofPosition = position;
|
||||
return remaining - c;
|
||||
}
|
||||
|
||||
@end
|
||||
|
423
Source/UdpPort.m
Normal file
423
Source/UdpPort.m
Normal file
|
@ -0,0 +1,423 @@
|
|||
/* Implementation of UDP port object for use with Connection
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: July 1994
|
||||
|
||||
This file is part of the GNU Objective C Class 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.
|
||||
*/
|
||||
|
||||
#include <objects/UdpPort.h>
|
||||
#include <objects/Lock.h>
|
||||
#include <objects/Connection.h>
|
||||
#include <objects/Coder.h>
|
||||
#include <objects/Array.h>
|
||||
#include <objects/ConnectedCoder.h>
|
||||
#include <objects/String.h>
|
||||
#include <assert.h>
|
||||
#if _AIX
|
||||
#include <sys/select.h>
|
||||
#endif /* _AIX */
|
||||
#ifndef WIN32
|
||||
#include <netdb.h>
|
||||
#include <sys/time.h>
|
||||
#endif /* !WIN32 */
|
||||
|
||||
@interface UdpInPort (Private)
|
||||
@end
|
||||
@interface UdpOutPort (Private)
|
||||
+ newForSendingToSockaddr: (struct sockaddr_in*)addr;
|
||||
@end
|
||||
@interface UdpPacket (Private)
|
||||
- (void) _setReplyPort: p;
|
||||
@end
|
||||
|
||||
/* The maximum size of packet UdpPort's will send or recieve. */
|
||||
/* xxx What is the UDP maximum? */
|
||||
#define MAX_PACKET_SIZE 2048
|
||||
|
||||
/* Make this a hashtable? */
|
||||
static Lock* udp_port_gate = nil;
|
||||
|
||||
static BOOL udp_port_debug = NO;
|
||||
|
||||
/* xxx This function is just temporary.
|
||||
Eventually we should write a real name server for sockets */
|
||||
static unsigned int
|
||||
name_to_port_number (const char *name)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
unsigned int ctr = 0;
|
||||
|
||||
/* xxx Limit the length? */
|
||||
while (*name)
|
||||
{
|
||||
ret ^= *name++ << ctr;
|
||||
ctr = (ctr + 1) % sizeof (void *);
|
||||
}
|
||||
return ret % (65535 - IPPORT_USERRESERVED - 1);
|
||||
}
|
||||
|
||||
@implementation UdpInPort
|
||||
|
||||
static NSMapTable *port_number_2_in_port = NULL;
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [UdpInPort class])
|
||||
{
|
||||
port_number_2_in_port =
|
||||
NSCreateMapTable (NSIntMapKeyCallBacks,
|
||||
NSNonOwnedPointerMapValueCallBacks, 0);
|
||||
}
|
||||
}
|
||||
|
||||
+ (void) setDebug: (BOOL)f
|
||||
{
|
||||
udp_port_debug = f;
|
||||
}
|
||||
|
||||
/* This is the designated initializer. */
|
||||
|
||||
/* An argument of 0 say to let the system choose the port number. */
|
||||
+ newForReceivingFromPortNumber: (unsigned short)n
|
||||
{
|
||||
UdpInPort* p;
|
||||
int i, count;
|
||||
|
||||
assert (n > IPPORT_USERRESERVED);
|
||||
|
||||
[udp_port_gate lock];
|
||||
|
||||
/* See if there is already one created */
|
||||
if ((p = NSMapGet (port_number_2_in_port, (void*)(int)n)))
|
||||
return p;
|
||||
|
||||
/* No, create a new one */
|
||||
p = [[self alloc] init];
|
||||
p->_address.sin_family = AF_INET;
|
||||
#if 1
|
||||
{
|
||||
struct hostent *hp;
|
||||
hp = gethostbyname ("localhost");
|
||||
assert (hp);
|
||||
memcpy (&(p->_address.sin_addr), hp->h_addr, sizeof(p->_address.sin_addr));
|
||||
}
|
||||
#else
|
||||
p->_address.sin_addr.s_addr = INADDR_ANY;
|
||||
#endif
|
||||
p->_address.sin_port = htons (n);
|
||||
if ((p->_socket = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
{
|
||||
perror("creating socket");
|
||||
abort ();
|
||||
}
|
||||
if (bind (p->_socket, (struct sockaddr*)&(p->_address), sizeof(p->_address)))
|
||||
{
|
||||
perror("bind");
|
||||
abort ();
|
||||
}
|
||||
if (udp_port_debug)
|
||||
fprintf(stderr, "created new UdpInPort 0x%x, fd=%d port_number=%d\n",
|
||||
(unsigned)p, p->_socket, -1);
|
||||
|
||||
/* Record it. */
|
||||
NSMapInsert (port_number_2_in_port, (void*)(int)n, p);
|
||||
[udp_port_gate unlock];
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
+ newForReceivingFromRegisteredName: (id <String>)name
|
||||
{
|
||||
int n;
|
||||
|
||||
n = name_to_port_number ([name cStringNoCopy]);
|
||||
return [self newForReceivingFromPortNumber: n];
|
||||
}
|
||||
|
||||
/* Returns nil on timeout.
|
||||
Pass -1 for milliseconds to ignore timeout parameter and block indefinitely.
|
||||
*/
|
||||
|
||||
- receivePacketWithTimeout: (int)milliseconds
|
||||
{
|
||||
int r;
|
||||
struct sockaddr_in remote_addr;
|
||||
int remote_len;
|
||||
UdpPacket *packet;
|
||||
|
||||
if (udp_port_debug)
|
||||
fprintf(stderr, "receiving from %d\n", [self portNumber]);
|
||||
|
||||
if (milliseconds >= 0)
|
||||
{
|
||||
/* A timeout was requested; use select to ask if something is ready. */
|
||||
struct timeval timeout;
|
||||
fd_set ready;
|
||||
|
||||
timeout.tv_sec = milliseconds / 1000;
|
||||
timeout.tv_usec = (milliseconds % 1000) * 1000;
|
||||
FD_ZERO(&ready);
|
||||
FD_SET(_socket, &ready);
|
||||
if ((r = select(_socket + 1, &ready, 0, 0, &timeout)) < 0)
|
||||
{
|
||||
perror("select");
|
||||
abort ();
|
||||
}
|
||||
|
||||
if (r == 0) /* timeout */
|
||||
return nil;
|
||||
if (!FD_ISSET(_socket, &ready))
|
||||
[self error:"select lied"];
|
||||
}
|
||||
|
||||
/* There is a packet on the socket ready for us to receive. */
|
||||
|
||||
/* Create a packet. */
|
||||
packet = [[UdpPacket alloc] initWithCapacity: MAX_PACKET_SIZE];
|
||||
|
||||
/* Fill it with the UDP packet data. */
|
||||
remote_len = sizeof(remote_addr);
|
||||
if (recvfrom (_socket, [packet streamBuffer], MAX_PACKET_SIZE, 0,
|
||||
(struct sockaddr*)&remote_addr, &remote_len)
|
||||
< 0)
|
||||
{
|
||||
perror("recvfrom");
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* Set the packet's reply_port. */
|
||||
if (remote_len != sizeof(struct sockaddr_in))
|
||||
[self error:"remote address size mismatch"];
|
||||
[packet _setReplyPort: [[self class] newForSendingToSockaddr: &remote_addr]];
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
- (void) invalidate
|
||||
{
|
||||
if (is_valid)
|
||||
{
|
||||
close (_socket);
|
||||
[super invalidate];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[self invalidate];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (int) socket
|
||||
{
|
||||
return _socket;
|
||||
}
|
||||
|
||||
- (int) portNumber
|
||||
{
|
||||
return (int) ntohs (_address.sin_port);
|
||||
}
|
||||
|
||||
- (Class) packetClass
|
||||
{
|
||||
return [UdpPacket class];
|
||||
}
|
||||
|
||||
- (Class) classForConnectedCoder: aRmc
|
||||
{
|
||||
/* Make sure that Connection's always send us bycopy, not a Proxy class.
|
||||
Also, don't encode a "receive right" (ala Mach), encode a "send right". */
|
||||
return [UdpOutPort class];
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: aCoder
|
||||
{
|
||||
/* We are actually encoding a "send right" (ala Mach),
|
||||
not a receive right. */
|
||||
[super encodeWithCoder: aCoder];
|
||||
[aCoder encodeValueOfCType: @encode(typeof(_address.sin_port))
|
||||
at: &_address.sin_port
|
||||
withName: @"socket number"];
|
||||
[aCoder encodeValueOfCType: @encode(typeof(_address.sin_addr.s_addr))
|
||||
at: &_address.sin_addr.s_addr
|
||||
withName: @"inet address"];
|
||||
}
|
||||
|
||||
+ newWithCoder: aCoder
|
||||
{
|
||||
/* An InPort cannot be created by decoding, only OutPort's. */
|
||||
[self shouldNotImplement: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation UdpOutPort
|
||||
|
||||
static Array *udp_out_port_array;
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [UdpOutPort class])
|
||||
{
|
||||
udp_out_port_array = [Array new];
|
||||
}
|
||||
}
|
||||
|
||||
#define SOCKPORT_EQUAL(s1,s2) (s1->sin_port == s2->sin_port && s1->sin_addr.s_addr == s2->sin_addr.s_addr)
|
||||
/* xxx Change to make INADDR_ANY and the localhost address be equal. */
|
||||
/* Assume that sin_family is equal */
|
||||
/* (!memcmp(s1, s2, sizeof(struct sockaddr_in)))
|
||||
didn't work because sin_zero's differ. Does this matter? */
|
||||
|
||||
|
||||
/* This is the designated initializer. */
|
||||
|
||||
+ newForSendingToSockaddr: (struct sockaddr_in*)sockaddr
|
||||
{
|
||||
UdpOutPort *p;
|
||||
|
||||
/* See if there already exists a port for this sockaddr;
|
||||
if so, just return it. */
|
||||
FOR_ARRAY (udp_out_port_array, p)
|
||||
{
|
||||
/* xxx Come up with a way to do this with a hashtable, not a list. */
|
||||
if (SOCKADDR_EQUAL (sockaddr, &(p->_address)))
|
||||
return p;
|
||||
}
|
||||
END_FOR_ARRAY (udp_out_port_array);
|
||||
|
||||
/* Create a new port. */
|
||||
p = [[self alloc] init];
|
||||
|
||||
/* Set the address. */
|
||||
memcpy (&(p->_address), sockaddr, sizeof(p->_address));
|
||||
|
||||
/* Remember it in the array. */
|
||||
/* xxx This will retain it; how will it ever get dealloc'ed? */
|
||||
[udp_out_port_array addObject: p];
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
+ newForSendingToPortNumber: (unsigned short)n
|
||||
onHost: (id <String>)hostname
|
||||
{
|
||||
struct hostent *hp;
|
||||
const char *host_cstring;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
/* Look up the hostname. */
|
||||
if (!hostname || ![hostname length])
|
||||
host_cstring = "localhost";
|
||||
else
|
||||
host_cstring = [hostname cStringNoCopy];
|
||||
hp = gethostbyname ((char*)host_cstring);
|
||||
if (hp == 0)
|
||||
[self error: "unknown host: \"%s\"", host_cstring];
|
||||
|
||||
/* Get the sockaddr_in address. */
|
||||
memcpy (&addr.sin_addr, hp->h_addr, hp->h_length);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons (n);
|
||||
|
||||
return [self newForSendingToSockaddr: &addr];
|
||||
}
|
||||
|
||||
|
||||
/* This currently ignores the timeout parameter */
|
||||
|
||||
- (BOOL) sendPacket: packet withTimeout: (int)milliseconds
|
||||
{
|
||||
id reply_port = [packet replyPort];
|
||||
int len = [packet streamEofPosition];
|
||||
|
||||
assert (len < MAX_PACKET_SIZE);
|
||||
|
||||
if ( ! [reply_port isKindOfClass: [UdpInPort class]])
|
||||
[self error:"Trying to send to a port that is not a UdpInPort"];
|
||||
if (udp_port_debug)
|
||||
fprintf (stderr, "sending to %d\n", (int) ntohs (_address.sin_port));
|
||||
if (sendto ([reply_port socket],
|
||||
[packet streamBuffer], len, 0,
|
||||
(struct sockaddr*)&_address, sizeof (_address))
|
||||
< 0)
|
||||
{
|
||||
perror ("sendto");
|
||||
abort ();
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (int) portNumber
|
||||
{
|
||||
return (int) ntohs (_address.sin_port);
|
||||
}
|
||||
|
||||
- (id <String>) hostname
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (Class) packetClass
|
||||
{
|
||||
return [UdpPacket class];
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: aCoder
|
||||
{
|
||||
[super encodeWithCoder: aCoder];
|
||||
[aCoder encodeValueOfCType: @encode(typeof(_address.sin_port))
|
||||
at: &_address.sin_port
|
||||
withName: @"socket number"];
|
||||
[aCoder encodeValueOfCType: @encode(typeof(_address.sin_addr.s_addr))
|
||||
at: &_address.sin_addr.s_addr
|
||||
withName: @"inet address"];
|
||||
}
|
||||
|
||||
+ newWithCoder: aCoder
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
[aCoder decodeValueOfCType: @encode(typeof(addr.sin_port))
|
||||
at: &addr.sin_port
|
||||
withName: NULL];
|
||||
[aCoder decodeValueOfCType: @encode(typeof(addr.sin_addr.s_addr))
|
||||
at: &addr.sin_addr.s_addr
|
||||
withName: NULL];
|
||||
return [UdpInPort newForSendingToSockaddr: &addr];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation UdpPacket
|
||||
|
||||
- (void) _setReplyPort: p
|
||||
{
|
||||
reply_port = p;
|
||||
}
|
||||
|
||||
@end
|
76
Source/objects/TcpPort.h
Normal file
76
Source/objects/TcpPort.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
/* Interface for stream based on TCP sockets
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: February 1996
|
||||
|
||||
This file is part of the GNU Objective C Class 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.
|
||||
*/
|
||||
|
||||
#ifndef __TcpPort_h__OBJECTS_INCLUDE
|
||||
#define __TcpPort_h__OBJECTS_INCLUDE
|
||||
|
||||
#include <objects/stdobjects.h>
|
||||
#include <objects/Port.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <Foundation/NSMapTable.h>
|
||||
|
||||
@interface TcpPacket : Packet
|
||||
@end
|
||||
|
||||
@interface TcpInPort : InPort
|
||||
{
|
||||
int _socket;
|
||||
struct sockaddr_in _address;
|
||||
fd_set active_fd_set;
|
||||
NSMapTable *client_sock_2_out_port;
|
||||
NSMapTable *client_sock_2_packet;
|
||||
}
|
||||
|
||||
+ newForReceivingFromPortNumber: (unsigned short)n;
|
||||
+ newForReceivingFromRegisteredName: (id <String>)name;
|
||||
|
||||
/* Get a packet from the net and return it. If no packet is received
|
||||
within MILLISECONDS, then return nil. The caller is responsible
|
||||
for releasing the packet. */
|
||||
- receivePacketWithTimeout: (int)milliseconds;
|
||||
|
||||
- (id <Collecting>) connectedOutPorts;
|
||||
|
||||
- (void) checkConnection;
|
||||
|
||||
@end
|
||||
|
||||
@interface TcpOutPort : OutPort
|
||||
{
|
||||
int _socket;
|
||||
struct sockaddr_in _address;
|
||||
id connected_in_port;
|
||||
}
|
||||
|
||||
+ newForSendingToPortNumber: (unsigned short)n
|
||||
onHost: (id <String>)hostname;
|
||||
+ newForSendingToRegisteredName: (id <String>)name
|
||||
onHost: (id <String>)hostname;
|
||||
- (BOOL) sendPacket: packet withTimeout: (int)milliseconds;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __TcpPort_h__OBJECTS_INCLUDE */
|
||||
|
59
Source/objects/UdpPort.h
Normal file
59
Source/objects/UdpPort.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* Interface for socket-based port object for use with Connection
|
||||
Copyright (C) 1994, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: July 1994
|
||||
|
||||
This file is part of the GNU Objective C Class 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.
|
||||
*/
|
||||
|
||||
#ifndef __SocketPort_h_INCLUDE_GNU
|
||||
#define __SocketPort_h_INCLUDE_GNU
|
||||
|
||||
#include <objects/stdobjects.h>
|
||||
#include <objects/Port.h>
|
||||
#include <sys/types.h>
|
||||
#ifndef WIN32
|
||||
# include <sys/socket.h>
|
||||
# include <netinet/in.h>
|
||||
#endif /* !WIN32 */
|
||||
|
||||
@interface UdpInPort : InPort
|
||||
{
|
||||
int _socket;
|
||||
struct sockaddr_in _address;
|
||||
}
|
||||
|
||||
- (int) portNumber;
|
||||
- (int) socket;
|
||||
|
||||
@end
|
||||
|
||||
@interface UdpOutPort : OutPort
|
||||
{
|
||||
struct sockaddr_in _address;
|
||||
}
|
||||
|
||||
- (int) portNumber;
|
||||
- (id <String>) hostname;
|
||||
|
||||
@end
|
||||
|
||||
@interface UdpPacket : Packet
|
||||
@end
|
||||
|
||||
#endif /* __SocketPort_h_INCLUDE_GNU */
|
Loading…
Reference in a new issue