1
/* Implementation of extension methods to base additions
3
Copyright (C) 2010 Free Software Foundation, Inc.
5
Written by: Richard Frith-Macdonald <rfm@gnu.org>
7
This file is part of the GNUstep Base Library.
9
This library is free software; you can redistribute it and/or
10
modify it under the terms of the GNU Lesser General Public
11
License as published by the Free Software Foundation; either
12
version 2 of the License, or (at your option) any later version.
14
This library is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
Library General Public License for more details.
19
You should have received a copy of the GNU Lesser General Public
20
License along with this library; if not, write to the Free
21
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27
#if defined(NeXT_Foundation_LIBRARY)
29
#import "Foundation/NSByteOrder.h"
30
#import "Foundation/NSHost.h"
33
#import "GNUstepBase/NSFileHandle+GNUstepBase.h"
35
/* Not defined on Solaris 2.7 */
37
#define INADDR_NONE -1
40
@implementation NSFileHandle(GNUstepBase)
41
// From GSFileHandle.m
44
getAddr(NSString* name, NSString* svc, NSString* pcl, struct addrinfo **ai, struct addrinfo *hints)
46
const char *cHostn = NULL;
47
const char *cPortn = NULL;
52
NSLog(@"service is nil.");
57
hints->ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
58
hints->ai_protocol = IPPROTO_IP; // accept any
62
if ([pcl isEqualToString:@"tcp"])
64
hints->ai_protocol = IPPROTO_TCP;
65
hints->ai_socktype = SOCK_STREAM;
67
else if ([pcl isEqualToString:@"udp"])
69
hints->ai_protocol = IPPROTO_UDP;
74
* If we were given a hostname, we use any address for that host.
75
* Otherwise we expect the given name to be an address unless it is
76
* a null (any address).
80
NSHost* host = [NSHost hostWithName: name];
84
name = [host address];
85
NSLog(@"host address '%@'", name);
86
cHostn = [name cStringUsingEncoding:NSASCIIStringEncoding];
90
cPortn = [svc cStringUsingEncoding:NSASCIIStringEncoding];
92
// getaddrinfo() returns zero on success or one of the error codes listed in
93
// gai_strerror(3) if an error occurs.
94
NSLog(@"cPortn '%s'", cPortn);
96
e = getaddrinfo (cHostn, cPortn, hints, ai);
100
NSLog(@"getaddrinfo: %s", gai_strerror (e));
107
- (id) initAsServerAtAddress: (NSString*)a
108
service: (NSString*)s
109
protocol: (NSString*)p
111
#ifndef BROKEN_SO_REUSEADDR
116
struct addrinfo hints;
117
memset (&hints, '\0', sizeof (hints));
119
if (getAddr(a, s, p, &ai, &hints) == NO)
122
NSLog(@"bad address-service-protocol combination");
126
if ((net = socket (ai->ai_family, ai->ai_socktype,
127
ai->ai_protocol)) < 0)
129
NSLog(@"unable to create socket ai_family: %@ socktype:%@ protocol:%d - %@", (ai->ai_family == PF_INET6 ? @"PF_INET6":@"PF_INET"),
130
(ai->ai_socktype == SOCK_STREAM ? @"SOCK_STREAM":@"whatever"),
137
#ifndef BROKEN_SO_REUSEADDR
139
* Under decent systems, SO_REUSEADDR means that the port can be reused
140
* immediately that this process exits. Under some it means
141
* that multiple processes can serve the same port simultaneously.
142
* We don't want that broken behavior!
144
setsockopt(net, SOL_SOCKET, SO_REUSEADDR, (char *)&status, sizeof(status));
147
if (bind(net, ai->ai_addr, ai->ai_addrlen) != 0)
149
NSLog(@"unable to bind to port %@", [NSError _last]);
153
if (listen(net, 5) < 0)
155
NSLog(@"unable to listen on port - %@", [NSError _last]);
159
// struct sockaddr_storeage sstore;
160
// int slen = sizeof(ss);
163
// if (getsockname(net,(struct sockaddr *)&sstore, &slen) < 0)
165
// NSLog(@"unable to get socket name - %@", [NSError _last]);
171
self = [self initWithFileDescriptor: net closeOnDealloc: YES];
183
+ (id) fileHandleAsServerAtAddress: (NSString*)address
184
service: (NSString*)service
185
protocol: (NSString*)protocol
187
id o = [self allocWithZone: NSDefaultMallocZone()];
189
return AUTORELEASE([o initAsServerAtAddress: address
191
protocol: protocol]);
194
- (NSString*) socketAddress
196
struct sockaddr_storage sstore;
197
struct sockaddr *sadr;
199
socklen_t size = sizeof(sstore);
201
if (getsockname([self fileDescriptor], (struct sockaddr*)&sstore, &size) < 0)
203
NSLog(@"unable to get socket name - %@", [NSError _last]);
207
sadr = (struct sockaddr *) &sstore;
209
switch (sadr->sa_family)
213
char straddr[INET6_ADDRSTRLEN];
214
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&sstore;
216
inet_ntop(AF_INET6, &(addr6->sin6_addr), straddr,
219
return [NSString stringWithCString: straddr
220
encoding: NSASCIIStringEncoding];
226
struct sockaddr_in * addr4 = (struct sockaddr_in*) &sstore;
228
char *address = inet_ntoa(addr4->sin_addr);
230
return [NSString stringWithCString: address
231
encoding: NSASCIIStringEncoding];
243
#endif /* defined(NeXT_Foundation_LIBRARY) */