Made dumper output a real IPv6 address
[ITFoundation.git] / ITInetSocket.m
1 //
2 //  ITInetSocket.m
3 //  ITFoundation
4 //
5 //  Created by Alexander Strange on Tue Feb 11 2003.
6 //  Copyright (c) 2003 __MyCompanyName__. All rights reserved.
7 //
8
9 #import "ITInetSocket.h"
10 #import <sys/socket.h>
11 #import <arpa/inet.h>
12
13 @interface ITInetSocket(Debugging)
14 -(NSString*)dumpv6Addrinfo:(struct addrinfo *)_ai;
15 @end
16
17 @implementation ITInetSocket
18 -(id)initWithFD:(int)fd delegate:(id)d
19 {
20     if (self = [super init])
21            {
22            state = ITInetSocketListening;
23            sockfd = fd;
24            delegate = [d retain];
25            port = 0;
26            writePipe = [[ITByteStream alloc] init];
27            readPipe = [[ITByteStream alloc] init];
28            ai = nil;
29            }
30     return self;
31 }
32
33 -(id)initWithDelegate:(id)d
34 {
35     if (self = [super init])
36            {
37            state = ITInetSocketDisconnected;
38            sockfd = -1;
39            delegate = [d retain];
40            port = 0;
41            writePipe = [[ITByteStream alloc] init];
42            readPipe = [[ITByteStream alloc] init];
43            ai = nil;
44            }
45     return self;
46 }
47
48 -(void) connectToHost:(NSString*)host onPort:(short)thePort
49 {
50     if (state == ITInetSocketDisconnected)
51            {
52            struct addrinfo hints;
53            int err;
54            const char *portNam = [[[NSNumber numberWithShort:thePort] stringValue] cString], *hostCStr = [host cString];
55
56            hints.ai_flags = 0;
57            hints.ai_family = PF_INET6;
58            hints.ai_socktype = SOCK_STREAM;
59            hints.ai_protocol = IPPROTO_TCP;
60            hints.ai_canonname = NULL;
61            hints.ai_addr = NULL;
62            hints.ai_next = NULL;
63
64            err = getaddrinfo(hostCStr,portNam,&hints,&ai);
65            if (err == EAI_NODATA) //it's a dotted-decimal IPv4 string, so we use v6compat stuff now
66            {
67                   err = getaddrinfo([[NSString stringWithFormat:@"ffff::%s",hostCStr] cString],portNam,&hints,&ai);
68            }
69            NSLog([self dumpv6Addrinfo:ai]);
70            }
71 }
72
73 -(ITInetSocketState)state
74 {
75     return state;
76 }
77 @end
78
79 @implementation ITInetSocket(Debugging)
80 -(NSString*)dumpv6Addrinfo:(struct addrinfo *)_ai
81 {
82     const char *cfmt =
83     "\{\n"
84     "Flags = %x\n"
85     "Family = %x\n"
86     "Socktype = %x\n"
87     "Protocol = %x\n"
88     "Canonname = %s\n"
89     "Sockaddr = \n"
90     "{\n"
91     "\tLength = %x\n"
92     "\tFamily = %x\n"
93     "\tPort = %d\n"
94     "\tFlowinfo = %x\n"
95     "\tAddr = {%#hx:%#hx:%#hx:%#hx:%#hx:%#hx:%#hx:%#hx}\n"
96     "\tScope = %x\n"
97     "}\n"
98     "Next = ";
99     NSString *nsfmt = [NSString stringWithCString:cfmt];
100     NSMutableString *buf = [[[NSMutableString alloc] init] autorelease];
101
102     do
103            {
104                   struct sockaddr_in6 *sa = (struct sockaddr_in6 *)_ai->ai_addr;
105                   [buf appendFormat:nsfmt,_ai->ai_flags,_ai->ai_family,_ai->ai_socktype,_ai->ai_protocol,_ai->ai_canonname?_ai->ai_canonname:"",sa->sin6_len,sa->sin6_family,sa->sin6_port,sa->sin6_flowinfo,sa->sin6_addr.__u6_addr.__u6_addr16[0],sa->sin6_addr.__u6_addr.__u6_addr16[1],sa->sin6_addr.__u6_addr.__u6_addr16[2],sa->sin6_addr.__u6_addr.__u6_addr16[3],sa->sin6_addr.__u6_addr.__u6_addr16[4],sa->sin6_addr.__u6_addr.__u6_addr16[5],sa->sin6_addr.__u6_addr.__u6_addr16[6],sa->sin6_addr.__u6_addr.__u6_addr16[7],sa->sin6_scope_id];
106            }
107     while (_ai = _ai->ai_next);
108     [buf appendString:@"nil\n}"];
109     return buf;
110 }
111 @end