VLCHTTPUploaderController.m 7.38 KB
Newer Older
1
2
3
4
/*****************************************************************************
 * VLCHTTPUploaderViewController.m
 * VLC for iOS
 *****************************************************************************
5
 * Copyright (c) 2013-2015 VideoLAN. All rights reserved.
6
7
8
9
10
11
12
13
14
 * $Id$
 *
 * Authors: Jean-Baptiste Kempf <jb # videolan.org>
 *          Gleb Pinigin <gpinigin # gmail.com>
 *          Felix Paul Kühne <fkuehne # videolan.org>
 *          Jean-Romain Prévost <jr # 3on.fr>
 *
 * Refer to the COPYING file of the official project for license.
 *****************************************************************************/
15

16
#import "VLCAppDelegate.h"
17
18
#import "VLCHTTPUploaderController.h"
#import "VLCHTTPConnection.h"
19
20
21

#import "HTTPServer.h"

22
23
24
#import <ifaddrs.h>
#import <arpa/inet.h>

25
@implementation VLCHTTPUploaderController
26
27
28
{
    UIBackgroundTaskIdentifier _backgroundTaskIdentifier;
}
29

30
31
- (id)init
{
Felix Paul Kühne's avatar
Felix Paul Kühne committed
32
    if (self = [super init]) {
33
34
        NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
        [center addObserver:self selector:@selector(applicationDidBecomeActive:)
35
            name:UIApplicationDidBecomeActiveNotification object:nil];
36
        [center addObserver:self selector:@selector(applicationDidEnterBackground:)
37
38
            name:UIApplicationDidEnterBackgroundNotification object:nil];
    }
Felix Paul Kühne's avatar
Felix Paul Kühne committed
39
40

    return self;
41
42
43
44
}

- (void)applicationDidBecomeActive: (NSNotification *)notification
{
45
46
47
48
49
50
51
    if (!self.httpServer.isRunning)
        [self changeHTTPServerState:[[NSUserDefaults standardUserDefaults] boolForKey:kVLCSettingSaveHTTPUploadServerStatus]];

    if (_backgroundTaskIdentifier && _backgroundTaskIdentifier != UIBackgroundTaskInvalid) {
        [[UIApplication sharedApplication] endBackgroundTask:_backgroundTaskIdentifier];
        _backgroundTaskIdentifier = 0;
    }
52
53
54
55
}

- (void)applicationDidEnterBackground: (NSNotification *)notification
{
56
57
    if (self.httpServer.isRunning) {
        if (!_backgroundTaskIdentifier || _backgroundTaskIdentifier == UIBackgroundTaskInvalid) {
58
            dispatch_block_t expirationHandler = ^{
59
60
61
                [self changeHTTPServerState:NO];
                [[UIApplication sharedApplication] endBackgroundTask:_backgroundTaskIdentifier];
                _backgroundTaskIdentifier = 0;
62
63
64
65
66
67
            };
            if ([[UIApplication sharedApplication] respondsToSelector:@selector(beginBackgroundTaskWithName:expirationHandler:)]) {
                _backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"VLCUploader" expirationHandler:expirationHandler];
            } else {
                _backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:expirationHandler];
            }
68
69
        }
    }
70
71
}

Felix Paul Kühne's avatar
Felix Paul Kühne committed
72
- (BOOL)changeHTTPServerState:(BOOL)state
73
{
Felix Paul Kühne's avatar
Felix Paul Kühne committed
74
75
76
77
    if (!state) {
        [self.httpServer stop];
        return true;
    }
78
79
80
    // clean cache before accepting new stuff
    [(VLCAppDelegate *)[UIApplication sharedApplication].delegate cleanCache];

Felix Paul Kühne's avatar
Felix Paul Kühne committed
81
82
83
    // Initialize our http server
    _httpServer = [[HTTPServer alloc] init];
    [_httpServer setInterface:WifiInterfaceName];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
84

85
86
87
    [_httpServer setIPv4Enabled:YES];
    [_httpServer setIPv6Enabled:[[[NSUserDefaults standardUserDefaults] objectForKey:kVLCSettingWiFiSharingIPv6] boolValue]];

Felix Paul Kühne's avatar
Felix Paul Kühne committed
88
89
90
    // Tell the server to broadcast its presence via Bonjour.
    // This allows browsers such as Safari to automatically discover our service.
    [self.httpServer setType:@"_http._tcp."];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
91

Felix Paul Kühne's avatar
Felix Paul Kühne committed
92
93
    // Serve files from the standard Sites folder
    NSString *docRoot = [[[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"] stringByDeletingLastPathComponent];
94

Felix Paul Kühne's avatar
Felix Paul Kühne committed
95
    APLog(@"Setting document root: %@", docRoot);
96

Felix Paul Kühne's avatar
Felix Paul Kühne committed
97
98
    [self.httpServer setDocumentRoot:docRoot];
    [self.httpServer setPort:80];
Felix Paul Kühne's avatar
Felix Paul Kühne committed
99

Felix Paul Kühne's avatar
Felix Paul Kühne committed
100
    [self.httpServer setConnectionClass:[VLCHTTPConnection class]];
101

Felix Paul Kühne's avatar
Felix Paul Kühne committed
102
103
    NSError *error = nil;
    if (![self.httpServer start:&error]) {
104
        if (error.code == EACCES) {
Felix Paul Kühne's avatar
Felix Paul Kühne committed
105
106
107
108
109
            APLog(@"Port forbidden by OS, trying another one");
            [self.httpServer setPort:8888];
            if(![self.httpServer start:&error])
                return true;
        }
110

Felix Paul Kühne's avatar
Felix Paul Kühne committed
111
        /* Address already in Use, take a random one */
112
        if (error.code == EADDRINUSE) {
Felix Paul Kühne's avatar
Felix Paul Kühne committed
113
114
115
116
            APLog(@"Port already in use, trying another one");
            [self.httpServer setPort:0];
            if(![self.httpServer start:&error])
                return true;
117
        }
Felix Paul Kühne's avatar
Felix Paul Kühne committed
118

119
        if (error) {
Felix Paul Kühne's avatar
Felix Paul Kühne committed
120
            APLog(@"Error starting HTTP Server: %@", error.localizedDescription);
121
122
            [self.httpServer stop];
        }
Felix Paul Kühne's avatar
Felix Paul Kühne committed
123
        return false;
124
    }
Felix Paul Kühne's avatar
Felix Paul Kühne committed
125
    return true;
126
127
}

128
129
130
131
132
133
- (NSString *)currentIPAddress
{
    NSString *address = @"";
    struct ifaddrs *interfaces = NULL;
    struct ifaddrs *temp_addr = NULL;
    int success = getifaddrs(&interfaces);
Felix Paul Kühne's avatar
Felix Paul Kühne committed
134

135
    if (success != 0) {
Felix Paul Kühne's avatar
Felix Paul Kühne committed
136
137
138
139
140
141
142
143
144
        freeifaddrs(interfaces);
        return address;
    }

    temp_addr = interfaces;
    while (temp_addr != NULL) {
        if (temp_addr->ifa_addr->sa_family == AF_INET) {
            if([@(temp_addr->ifa_name) isEqualToString:WifiInterfaceName])
                address = @(inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr));
145
        }
Felix Paul Kühne's avatar
Felix Paul Kühne committed
146
        temp_addr = temp_addr->ifa_next;
147
    }
Felix Paul Kühne's avatar
Felix Paul Kühne committed
148

149
150
151
152
    freeifaddrs(interfaces);
    return address;
}

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
- (NSString *)hostname
{
    char baseHostName[256];
    int success = gethostname(baseHostName, 255);
    if (success != 0)
        return nil;
    baseHostName[255] = '\0';

#if !TARGET_IPHONE_SIMULATOR
    return [NSString stringWithFormat:@"%s.local", baseHostName];
#else
    return [NSString stringWithFormat:@"%s", baseHostName];
#endif
}

168
169
170
171
172
173
174
175
176
177
178
179
180
181
- (void)moveFileFrom:(NSString *)filepath
{
    NSString *fileName = [filepath lastPathComponent];
    NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *libraryPath = searchPaths[0];
    NSString *finalFilePath = [libraryPath stringByAppendingPathComponent:fileName];
    NSFileManager *fileManager = [NSFileManager defaultManager];

    if ([fileManager fileExistsAtPath:finalFilePath]) {
        /* we don't want to over-write existing files, so add an integer to the file name */
        NSString *potentialFilename;
        NSString *fileExtension = [fileName pathExtension];
        NSString *rawFileName = [fileName stringByDeletingPathExtension];
        for (NSUInteger x = 1; x < 100; x++) {
182
            potentialFilename = [NSString stringWithFormat:@"%@ %lu.%@", rawFileName, (unsigned long)x, fileExtension];
183
184
185
186
187
188
189
190
191
            if (![[NSFileManager defaultManager] fileExistsAtPath:[libraryPath stringByAppendingPathComponent:potentialFilename]])
                break;
        }
        finalFilePath = [libraryPath stringByAppendingPathComponent:potentialFilename];
    }

    NSError *error;
    [fileManager moveItemAtPath:filepath toPath:finalFilePath error:&error];
    if (error) {
192
        APLog(@"Moving received media %@ to library folder failed (%li), deleting", fileName, (long)error.code);
193
194
195
        [fileManager removeItemAtPath:filepath error:nil];
    }

196
    [(VLCAppDelegate*)[UIApplication sharedApplication].delegate networkActivityStopped];
197
198
199
200
    [(VLCAppDelegate*)[UIApplication sharedApplication].delegate activateIdleTimer];

    /* update media library when file upload was completed */
    VLCAppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
201
    [appDelegate performSelectorOnMainThread:@selector(updateMediaList) withObject:nil waitUntilDone:NO];
202
203
}

204
@end