1/* 2 * Copyright (c) 2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <notify.h> 25#include <stdio.h> 26#include <IOKit/platform/IOPlatformSupportPrivate.h> 27#include "Platform.h" 28#include "PrivateLib.h" 29#include "PMSettings.h" 30 31__private_extern__ CFAbsoluteTime get_SleepFromUserWakeTime(); 32 33__private_extern__ TCPKeepAliveStruct *gTCPKeepAlive = NULL; 34 35#define kTCPWakeQuotaCountDefault 20 36#define kTCPWakeQuotaIntervalSecDefault 3ULL*60ULL*60ULL 37 38 39 40static void lazyAllocTCPKeepAlive(void) 41{ 42 CFDictionaryRef platformFeatures = NULL; 43 CFNumberRef expirationTimeout = NULL; 44 45 if (gTCPKeepAlive) { 46 return; 47 } 48 49 platformFeatures = _copyRootDomainProperty(CFSTR("IOPlatformFeatureDefaults")); 50 if (platformFeatures) 51 { 52 gTCPKeepAlive = calloc(1, sizeof(TCPKeepAliveStruct)); 53 if (!gTCPKeepAlive) return; 54 55 if (kCFBooleanTrue == CFDictionaryGetValue(platformFeatures, 56 kIOPlatformTCPKeepAliveDuringSleep)) 57 { 58 if ((expirationTimeout = CFDictionaryGetValue(platformFeatures, 59 CFSTR("TCPKeepAliveExpirationTimeout")))) 60 { 61 CFNumberGetValue(expirationTimeout, kCFNumberLongType, &gTCPKeepAlive->overrideSec); 62 } 63 gTCPKeepAlive->state = kActive; 64 } 65 else { 66 gTCPKeepAlive->state = kNotSupported; 67 } 68 CFRelease(platformFeatures); 69 } 70 71 return; 72} 73 74__private_extern__ void cancelTCPKeepAliveExpTimer( ) 75{ 76 77 if (gTCPKeepAlive && gTCPKeepAlive->expiration) 78 dispatch_source_cancel(gTCPKeepAlive->expiration); 79} 80__private_extern__ void startTCPKeepAliveExpTimer( ) 81{ 82 if ((!gTCPKeepAlive) || (gTCPKeepAlive->state != kActive)) return; 83 84 if (!gTCPKeepAlive->expiration) { 85 gTCPKeepAlive->expiration = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 86 0, dispatch_get_main_queue()); 87 dispatch_source_set_event_handler(gTCPKeepAlive->expiration, ^{ 88 gTCPKeepAlive->state = kInactive; 89 configAssertionType(kInteractivePushServiceType, false); 90 }); 91 dispatch_source_set_cancel_handler(gTCPKeepAlive->expiration, ^{ 92 if (gTCPKeepAlive->expiration) { 93 dispatch_release(gTCPKeepAlive->expiration); 94 gTCPKeepAlive->expiration = 0; 95 gTCPKeepAlive->state = kActive; 96 } 97 }); 98 } 99 else { 100 dispatch_suspend(gTCPKeepAlive->expiration); 101 } 102 103 dispatch_source_set_timer(gTCPKeepAlive->expiration, 104 dispatch_walltime(NULL, kTCPKeepAliveExpireSecs * NSEC_PER_SEC), 105 DISPATCH_TIME_FOREVER, 0); 106 dispatch_resume(gTCPKeepAlive->expiration); 107 108} 109 110__private_extern__ 111tcpKeepAliveStates_et getTCPKeepAliveState(char *buf, int buflen) 112{ 113 lazyAllocTCPKeepAlive(); 114 115 if (!gTCPKeepAlive || (gTCPKeepAlive->state == kNotSupported)) 116 { 117 if (buf) snprintf(buf, buflen, "unsupported"); 118 return kNotSupported; 119 } 120 121 if (buf) { 122 if (gTCPKeepAlive->state == kActive) 123 snprintf(buf, buflen, "active"); 124 else 125 snprintf(buf, buflen, "inactive"); 126 } 127 return gTCPKeepAlive->state; 128 129} 130 131 132