~ubuntu-branches/ubuntu/trusty/gnustep-base/trusty

« back to all changes in this revision

Viewing changes to Source/Additions/NSFileHandle+GNUstepBase.m

Tags: upstream-1.20.0
ImportĀ upstreamĀ versionĀ 1.20.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Implementation of extension methods to base additions
 
2
 
 
3
   Copyright (C) 2010 Free Software Foundation, Inc.
 
4
 
 
5
   Written by:  Richard Frith-Macdonald <rfm@gnu.org>
 
6
 
 
7
   This file is part of the GNUstep Base Library.
 
8
 
 
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.
 
13
 
 
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.
 
18
 
 
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,
 
22
   Boston, MA 02111 USA.
 
23
 
 
24
*/
 
25
#import "common.h"
 
26
 
 
27
#if     defined(NeXT_Foundation_LIBRARY)
 
28
 
 
29
#import "Foundation/NSByteOrder.h"
 
30
#import "Foundation/NSHost.h"
 
31
#import "GSNetwork.h"
 
32
#import "GSPrivate.h"
 
33
#import "GNUstepBase/NSFileHandle+GNUstepBase.h"
 
34
 
 
35
/* Not defined on Solaris 2.7 */
 
36
#ifndef INADDR_NONE
 
37
#define INADDR_NONE     -1
 
38
#endif
 
39
 
 
40
@implementation NSFileHandle(GNUstepBase)
 
41
// From GSFileHandle.m
 
42
 
 
43
static BOOL
 
44
getAddr(NSString* name, NSString* svc, NSString* pcl, struct addrinfo **ai, struct addrinfo *hints)
 
45
{
 
46
  const char        *cHostn = NULL;
 
47
  const char        *cPortn = NULL;
 
48
  int                e = 0;
 
49
 
 
50
  if (!svc)
 
51
    {
 
52
      NSLog(@"service is nil.");
 
53
      
 
54
      return NO;
 
55
    }
 
56
 
 
57
  hints->ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
 
58
  hints->ai_protocol = IPPROTO_IP; // accept any
 
59
 
 
60
  if (pcl)
 
61
    {
 
62
      if ([pcl isEqualToString:@"tcp"])
 
63
        {
 
64
          hints->ai_protocol = IPPROTO_TCP;
 
65
          hints->ai_socktype = SOCK_STREAM;
 
66
        }
 
67
      else if ([pcl isEqualToString:@"udp"])
 
68
        {
 
69
          hints->ai_protocol = IPPROTO_UDP;
 
70
        } 
 
71
    }
 
72
 
 
73
  /*
 
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).
 
77
   */
 
78
  if (name)
 
79
    {
 
80
      NSHost*        host = [NSHost hostWithName: name];
 
81
      
 
82
      if (host != nil)
 
83
        {
 
84
          name = [host address];
 
85
          NSLog(@"host address '%@'", name);
 
86
          cHostn = [name cStringUsingEncoding:NSASCIIStringEncoding];
 
87
        }
 
88
    }
 
89
  
 
90
  cPortn = [svc cStringUsingEncoding:NSASCIIStringEncoding];
 
91
  
 
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);
 
95
                                           //&ai
 
96
  e = getaddrinfo (cHostn, cPortn, hints, ai);
 
97
 
 
98
  if (e != 0)
 
99
    {
 
100
      NSLog(@"getaddrinfo: %s", gai_strerror (e));
 
101
      return NO;
 
102
    }
 
103
 
 
104
  return YES;
 
105
}
 
106
 
 
107
- (id) initAsServerAtAddress: (NSString*)a
 
108
                     service: (NSString*)s
 
109
                    protocol: (NSString*)p
 
110
{
 
111
#ifndef    BROKEN_SO_REUSEADDR
 
112
  int    status = 1;
 
113
#endif
 
114
  int    net;
 
115
  struct addrinfo *ai;
 
116
  struct addrinfo hints;
 
117
  memset (&hints, '\0', sizeof (hints));
 
118
 
 
119
  if (getAddr(a, s, p, &ai, &hints) == NO)
 
120
    {
 
121
      DESTROY(self);
 
122
      NSLog(@"bad address-service-protocol combination");
 
123
      return  nil;
 
124
    }
 
125
 
 
126
  if ((net = socket (ai->ai_family, ai->ai_socktype,
 
127
                     ai->ai_protocol)) < 0)
 
128
    {
 
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"),
 
131
            ai->ai_protocol,            
 
132
            [NSError _last]);
 
133
      DESTROY(self);
 
134
      return nil;
 
135
    }
 
136
 
 
137
#ifndef    BROKEN_SO_REUSEADDR
 
138
  /*
 
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!
 
143
   */
 
144
  setsockopt(net, SOL_SOCKET, SO_REUSEADDR, (char *)&status,  sizeof(status));
 
145
#endif
 
146
 
 
147
  if (bind(net, ai->ai_addr, ai->ai_addrlen) != 0)
 
148
    {
 
149
      NSLog(@"unable to bind to port %@", [NSError _last]);
 
150
      goto cleanup;
 
151
    }
 
152
 
 
153
  if (listen(net, 5) < 0)
 
154
    {
 
155
      NSLog(@"unable to listen on port - %@",  [NSError _last]);
 
156
      goto cleanup;
 
157
    }
 
158
 
 
159
  //    struct sockaddr_storeage sstore;
 
160
  //    int slen = sizeof(ss);
 
161
 
 
162
 
 
163
//  if (getsockname(net,(struct sockaddr *)&sstore, &slen) < 0)
 
164
//    {
 
165
//      NSLog(@"unable to get socket name - %@",  [NSError _last]);
 
166
//      goto cleanup;
 
167
//    }
 
168
 
 
169
  freeaddrinfo (ai);
 
170
  
 
171
  self = [self initWithFileDescriptor: net closeOnDealloc: YES];
 
172
 
 
173
  return self;
 
174
  
 
175
cleanup:
 
176
  (void) close(net);
 
177
  freeaddrinfo (ai);
 
178
  DESTROY(self);
 
179
  
 
180
  return nil;
 
181
}
 
182
 
 
183
+ (id) fileHandleAsServerAtAddress: (NSString*)address
 
184
                           service: (NSString*)service
 
185
                          protocol: (NSString*)protocol
 
186
{
 
187
  id    o = [self allocWithZone: NSDefaultMallocZone()];
 
188
 
 
189
  return AUTORELEASE([o initAsServerAtAddress: address
 
190
                                      service: service
 
191
                                     protocol: protocol]);
 
192
}
 
193
 
 
194
- (NSString*) socketAddress
 
195
{
 
196
  struct sockaddr_storage    sstore;
 
197
  struct sockaddr            *sadr;
 
198
  
 
199
  socklen_t    size = sizeof(sstore);
 
200
  
 
201
  if (getsockname([self fileDescriptor], (struct sockaddr*)&sstore,  &size) < 0)
 
202
    {
 
203
      NSLog(@"unable to get socket name - %@",  [NSError _last]);
 
204
      return nil;
 
205
    }
 
206
  
 
207
  sadr = (struct sockaddr *) &sstore;
 
208
  
 
209
  switch (sadr->sa_family)
 
210
    {
 
211
      case AF_INET6:
 
212
        {
 
213
          char straddr[INET6_ADDRSTRLEN];
 
214
          struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&sstore;
 
215
          
 
216
          inet_ntop(AF_INET6, &(addr6->sin6_addr), straddr, 
 
217
                    sizeof(straddr));
 
218
          
 
219
          return [NSString stringWithCString: straddr 
 
220
                                    encoding: NSASCIIStringEncoding];
 
221
          break;
 
222
        }
 
223
      case AF_INET:
 
224
        {
 
225
          
 
226
          struct sockaddr_in * addr4 = (struct sockaddr_in*) &sstore;
 
227
          
 
228
          char *address = inet_ntoa(addr4->sin_addr);
 
229
          
 
230
          return [NSString stringWithCString: address 
 
231
                                    encoding: NSASCIIStringEncoding];
 
232
          break;
 
233
        } 
 
234
      default:
 
235
        break;
 
236
    }
 
237
  
 
238
  return nil;
 
239
}
 
240
 
 
241
@end
 
242
 
 
243
#endif  /* defined(NeXT_Foundation_LIBRARY) */
 
244