1//
2// Copyright (c) ZeroC, Inc. All rights reserved.
3//
4
5#import "ControllerView.h"
6
7#include <ifaddrs.h>
8#include <arpa/inet.h>
9#include <net/if.h>
10
11@implementation ControllerView
12
13- (void)viewDidLoad
14{
15    [super viewDidLoad];
16
17    //
18    // Load the controller bundle.
19    //
20    NSString* bundlePath = [[NSBundle mainBundle] privateFrameworksPath];
21#ifdef ICE_CPP11_MAPPING
22    const char* bundle = "Cpp11ControllerBundle.bundle";
23#else
24    const char* bundle = "Cpp98ControllerBundle.bundle";
25#endif
26    bundlePath = [bundlePath stringByAppendingPathComponent:[NSString stringWithUTF8String:bundle]];
27
28    NSURL* bundleURL = [NSURL fileURLWithPath:bundlePath];
29    CFBundleRef handle = CFBundleCreate(NULL, (CFURLRef)bundleURL);
30    if(!handle)
31    {
32        [self println:[NSString stringWithFormat:@"Could not find bundle %@", bundlePath]];
33        return;
34    }
35
36    CFErrorRef error = nil;
37    Boolean loaded = CFBundleLoadExecutableAndReturnError(handle, &error);
38    if(error != nil || !loaded)
39    {
40        [self println:[(__bridge NSError *)error description]];
41        return;
42    }
43
44    startController = CFBundleGetFunctionPointerForName(handle, CFSTR("startController"));
45    if(startController == 0)
46    {
47        NSString* err = [NSString stringWithFormat:@"Could not get function pointer startController from bundle %@",
48                         bundlePath];
49        [self println:err];
50        return;
51    }
52
53    stopController = CFBundleGetFunctionPointerForName(handle, CFSTR("stopController"));
54    if(stopController == 0)
55    {
56        NSString* err = [NSString stringWithFormat:@"Could not get function pointer stopController from bundle %@",
57                         bundlePath];
58        [self println:err];
59        return;
60    }
61
62    //
63    // Search for local network interfaces
64    //
65    interfacesIPv4 = [NSMutableArray array];
66    [interfacesIPv4 addObject:@"127.0.0.1"];
67    interfacesIPv6 = [NSMutableArray array];
68    [interfacesIPv6 addObject:@"::1"];
69    struct ifaddrs* ifap;
70    if(getifaddrs(&ifap) == 0)
71    {
72        struct ifaddrs* curr = ifap;
73        while(curr != 0)
74        {
75            if(curr->ifa_addr && curr->ifa_flags & IFF_UP && !(curr->ifa_flags & IFF_LOOPBACK))
76            {
77                if(curr->ifa_addr->sa_family == AF_INET)
78                {
79                    char buf[INET_ADDRSTRLEN];
80                    const struct sockaddr_in *addr = (const struct sockaddr_in*)curr->ifa_addr;
81                    if(inet_ntop(AF_INET, &addr->sin_addr, buf, INET_ADDRSTRLEN))
82                    {
83                        [interfacesIPv4 addObject:[NSString stringWithUTF8String:buf]];
84                    }
85                }
86                else if(curr->ifa_addr->sa_family == AF_INET6)
87                {
88                    char buf[INET6_ADDRSTRLEN];
89                    const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)curr->ifa_addr;
90                    if(inet_ntop(AF_INET6, &addr6->sin6_addr, buf, INET6_ADDRSTRLEN))
91                    {
92                        [interfacesIPv6 addObject:[NSString stringWithUTF8String:buf]];
93                    }
94                }
95            }
96            curr = curr->ifa_next;
97        }
98        freeifaddrs(ifap);
99    }
100
101    // By default, use the loopback
102    [interfaceIPv4 selectRow:0 inComponent:0 animated:NO];
103    [interfaceIPv6 selectRow:0 inComponent:0 animated:NO];
104    (*startController)(self,
105                       [interfacesIPv4 objectAtIndex:[interfaceIPv4 selectedRowInComponent:0]],
106                       [interfacesIPv6 objectAtIndex:[interfaceIPv6 selectedRowInComponent:0]]);
107}
108
109- (void) dealloc
110{
111    (*stopController)(self);
112}
113
114-(void) write:(NSString*)msg
115{
116    [output insertText:msg];
117    [output layoutIfNeeded];
118    [output scrollRangeToVisible:NSMakeRange([output.text length] - 1, 1)];
119}
120
121#pragma mark ControllerView
122
123-(void) print:(NSString*)msg
124{
125    [self performSelectorOnMainThread:@selector(write:) withObject:msg waitUntilDone:NO];
126}
127-(void) println:(NSString*)msg
128{
129    [self print:[msg stringByAppendingString:@"\n"]];
130}
131
132#pragma mark UIPickerViewDelegate
133
134- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
135{
136    if(pickerView == interfaceIPv4)
137    {
138        return [interfacesIPv4 objectAtIndex:row];
139    }
140    else
141    {
142        return [interfacesIPv6 objectAtIndex:row];
143    }
144}
145
146- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
147{
148    (*stopController)(self);
149    (*startController)(self,
150                       [interfacesIPv4 objectAtIndex:[interfaceIPv4 selectedRowInComponent:0]],
151                       [interfacesIPv6 objectAtIndex:[interfaceIPv6 selectedRowInComponent:0]]);
152}
153
154#pragma mark UIPickerViewDataSource
155
156- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
157{
158    return 1;
159}
160
161- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
162{
163    if(pickerView == interfaceIPv4)
164    {
165        return interfacesIPv4.count;
166    }
167    else
168    {
169        return interfacesIPv6.count;
170    }
171}
172
173@end
174