]> err.no Git - sope/blob - sope-core/NGStreams/NGLocalSocketAddress.m
Drop apache 1 build-dependency
[sope] / sope-core / NGStreams / NGLocalSocketAddress.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with SOPE; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21
22 #if !defined(WIN32) || defined(__CYGWIN32__)
23
24 #include "NGSocketExceptions.h"
25 #include "NGLocalSocketAddress.h"
26 #include "NGLocalSocketDomain.h"
27 #import <Foundation/NSString.h>
28
29 #include "config.h"
30
31 #if defined(__APPLE__) || defined(__FreeBSD__)
32 #  include <sys/types.h>
33 #else
34 #  include <sys/un.h>
35 #endif
36
37 #if defined(HAVE_UNISTD_H) || defined(__APPLE__)
38 #  include <unistd.h>
39 #endif
40
41 #ifndef SUN_LEN
42 #define SUN_LEN(su) \
43         (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
44 #endif
45
46 #include "common.h"
47
48 #ifndef AF_LOCAL
49 #  define AF_LOCAL AF_UNIX
50 #endif
51
52 #if defined(__WIN32__) && !defined(__CYGWIN32__)
53 static NSString *socketDirectoryPath = @"\\\\.\\pipe\\";
54 #else
55 static NSString *socketDirectoryPath = @"/tmp";
56 #endif
57
58 @implementation NGLocalSocketAddress
59
60 + (id)addressWithPath:(NSString *)_p {
61   return [[(NGLocalSocketAddress *)[self alloc] initWithPath:_p] autorelease];
62 }
63 + (id)address {
64   return [[[self alloc] init] autorelease];
65 }
66
67 - (id)initWithPath:(NSString *)_path {
68   if ((self = [super init])) {
69     self->address = calloc(1, sizeof(struct sockaddr_un));
70     
71     memset(self->address, 0, sizeof(struct sockaddr_un));
72     
73 #if defined(__WIN32__) && !defined(__CYGWIN32__)
74     self->path = [_path copyWithZone:[self zone]];
75 #else
76     if ([_path cStringLength] >=
77         sizeof(((struct sockaddr_un *)self->address)->sun_path)) {
78       
79       NSLog(@"LocalDomain name too long: maxlen=%i, len=%i, path=%@",
80             sizeof(((struct sockaddr_un *)self->address)->sun_path),
81             [_path cStringLength],
82             _path);
83       [NSException raise:NSInvalidArgumentException
84                    format:@"path to long as local domain socket address !"];
85       [self release];
86       return nil;
87     }
88     
89     ((struct sockaddr_un *)self->address)->sun_family =
90       [[self domain] socketDomain];
91
92     [_path getCString:((struct sockaddr_un *)self->address)->sun_path
93            maxLength:sizeof(((struct sockaddr_un *)self->address)->sun_path)];
94 #endif
95   }
96   return self;
97 }
98
99 - (id)init {
100   int      addressCounter = 0;
101   NSString *newPath;
102   
103   newPath = [NSString stringWithFormat:@"_ngsocket_%p_%p_%03d",
104                         getpid(), [NSThread currentThread], addressCounter];
105   newPath = [socketDirectoryPath stringByAppendingPathComponent:newPath];
106
107   return [self initWithPath:newPath];
108 }
109
110 - (id)initWithDomain:(id)_domain
111   internalRepresentation:(void *)_representation
112   size:(int)_length
113 {
114   // this method is used by the address factory
115   struct sockaddr_un *nun = _representation;
116   NSString *path;
117
118   path = (_length < 3)
119     ? (id)@""
120     : [[NSString alloc] initWithCString:nun->sun_path];
121   
122   self = [self initWithPath:path];
123   [path release]; path = nil;
124   return self;
125 }
126
127 - (void)dealloc {
128   if (self->address) free(self->address);
129   [super dealloc];
130 }
131
132 /* accessors */
133
134 - (NSString *)path {
135   const char *sp;
136
137   sp = ((struct sockaddr_un *)self->address)->sun_path;
138   if (strlen(sp) == 0)
139     return @"";
140   
141   return [NSString stringWithCString:sp];
142 }
143
144 /* operations */
145
146 - (void)deletePath {
147   const char *sp;
148   
149   sp = ((struct sockaddr_un *)self->address)->sun_path;
150   if (strlen(sp) == 0)
151     return;
152   
153   unlink(sp);
154 }
155
156 // NGSocketAddress protocol
157
158 - (void *)internalAddressRepresentation {
159   return self->address;
160 }
161 - (int)addressRepresentationSize { // varies in length
162   return SUN_LEN(((struct sockaddr_un *)self->address));
163 }
164 - (id)domain {
165   return [NGLocalSocketDomain domain];
166 }
167
168 /* test for accessibility */
169
170 - (BOOL)canSendOnAddress {
171   return (access(((struct sockaddr_un *)self->address)->sun_path, W_OK) == 0)
172     ? YES : NO;
173 }
174 - (BOOL)canReceiveOnAddress {
175   return (access(((struct sockaddr_un *)self->address)->sun_path, R_OK) == 0)
176     ? YES : NO;
177 }
178
179 /* testing for equality */
180
181 - (BOOL)isEqualToAddress:(NGLocalSocketAddress *)_addr {
182   return [[_addr path] isEqualToString:[self path]];
183 }
184
185 - (BOOL)isEqual:(id)_object {
186   if (_object == self) return YES;
187   if ([_object class] != [self class]) return NO;
188   return [self isEqualToAddress:_object];
189 }
190
191 /* NSCopying */
192
193 - (id)copyWithZone:(NSZone *)_zone {
194   /* socket addresses are immutable, just retain on copy ... */
195   return [self retain];
196 }
197
198 /* NSCoding */
199
200 - (void)encodeWithCoder:(NSCoder *)_encoder {
201   [_encoder encodeObject:[[NSHost currentHost] name]];
202   [_encoder encodeObject:[self path]];
203 }
204
205 - (id)initWithCoder:(NSCoder *)_decoder {
206   NSString *hostName = [_decoder decodeObject];
207   NSString *path     = [_decoder decodeObject];
208
209   NSAssert([path isKindOfClass:[NSString class]], @"path must be a string ..");
210
211   if (![hostName isEqualToString:[[NSHost currentHost] name]]) {
212     NSLog(@"unarchived local socket address on a different host, "
213           @"encoded on %@, decoded on %@ (path=%@)",
214           hostName, [[NSHost currentHost] name], path);
215   }
216
217   return [self initWithPath:path];
218 }
219
220 /* description */
221
222 - (NSString *)stringValue {
223   NSString *p = [self path];
224   return [p length] == 0 ? (NSString *)@"*" : p;
225 }
226
227 - (NSString *)description {
228   NSString *p = [self path];
229   
230   if ([p length] == 0)
231     p = @"[no path]";
232
233   return [NSString stringWithFormat:@"<0x%p[%@]: %@>",
234                      self, NSStringFromClass([self class]), p];
235 }
236
237 @end /* NGLocalSocketAddress */
238
239 #endif /* !WIN32 */