Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TIMOB-24017] Added support for validating the connection to the log server. #8503

Merged
merged 4 commits into from
Oct 13, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
50 changes: 47 additions & 3 deletions iphone/Classes/TiLogServer.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,22 @@
* infinite loop of death. Use forcedNSLog() instead.
*/

/**
* iOS platform hackers: when you manually run this project from Xcode, it may
* be handy, but not necessary, to connect to the log server and here's some
* Node.js code to help:
*
* require('net').connect(10571)
* .on('data', data => process.stdout.write(data.toString()))
* .on('error', err => console.log('Error:', err))
* .on('end', () => console.log('Disconnected from server'));
*/

#ifndef DISABLE_TI_LOG_SERVER

#import "TiLogServer.h"
#import "TiBase.h"
#import "TiUtils.h"
#include <sys/socket.h>
#include <netinet/in.h>

Expand All @@ -32,6 +44,12 @@
# define TI_LOG_SERVER_QUEUE_SIZE 100
#endif

extern NSString* const TI_APPLICATION_NAME;
extern NSString* const TI_APPLICATION_ID;
extern NSString* const TI_APPLICATION_VERSION;
extern NSString* const TI_APPLICATION_DEPLOYTYPE;
extern NSString* const TI_APPLICATION_GUID;

/**
* All log server state is global mainly because there should only be one log
* server.
Expand All @@ -41,6 +59,7 @@
static int logServerSocket = -1;
static NSMutableArray* connections = nil;
static NSMutableArray* logQueue = nil;
static NSData* headers = nil;

/**
* Helper function to force logging with NSLog() since we override it. Used only
Expand Down Expand Up @@ -223,6 +242,23 @@ +(void)startServer
connections = [[NSMutableArray alloc] init];
}

if (headers == nil) {
NSString* version = [NSString stringWithCString:TI_VERSION_STR encoding:NSUTF8StringEncoding];
NSDictionary* map = [[NSDictionary alloc] initWithObjectsAndKeys:
TI_APPLICATION_NAME, @"name",
TI_APPLICATION_ID, @"appId",
TI_APPLICATION_VERSION, @"version",
TI_APPLICATION_DEPLOYTYPE, @"deployType",
TI_APPLICATION_GUID, @"guid",
version, @"tiSDKVersion",
@"__GITHASH__", @"githash",
nil];

headers = [[[[TiUtils jsonStringify:map] stringByAppendingString:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding] retain];

[map release];
}

// create the listening socket
logServerSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (logServerSocket == -1) {
Expand Down Expand Up @@ -283,6 +319,13 @@ +(void)startServer
[connections addObject:conn];
forcedNSLog(@"[INFO] Log server connections: %d", [connections count]);

// send the header
dispatch_data_t buffer = dispatch_data_create(headers.bytes,
headers.length,
logDispatchQueue,
DISPATCH_DATA_DESTRUCTOR_DEFAULT);
[conn send:&buffer];

// if log queue exists, flush the whole thing and nuke it
if (logQueue != nil) {
for (id message in logQueue) {
Expand Down Expand Up @@ -325,6 +368,9 @@ +(void)stopServer
RELEASE_TO_NIL(connections);
}

// release the headers buffer
RELEASE_TO_NIL(headers);

// release the dispatch source
if (logDispatchSource != nil) {
dispatch_source_cancel(logDispatchSource);
Expand All @@ -338,9 +384,7 @@ +(void)stopServer
}

// release any retained messages in the log queue
if (logQueue != nil) {
RELEASE_TO_NIL(logQueue);
}
RELEASE_TO_NIL(logQueue);
}

@end // end TiLogServer
Expand Down
15 changes: 15 additions & 0 deletions iphone/cli/commands/_build.js
Original file line number Diff line number Diff line change
Expand Up @@ -1461,6 +1461,13 @@ iOSBuilder.prototype.validate = function (logger, config, cli) {
this.tiapp.ios.capabilities || (this.tiapp.ios.capabilities = {});
this.tiapp.ios.extensions || (this.tiapp.ios.extensions = []);

// validate the log server port
var logServerPort = this.tiapp.ios['log-server-port'];
if (!/^dist-(appstore|adhoc)$/.test(this.target) && (typeof logServerPort !== 'number' || logServerPort < 1 || logServerPort > 65535)) {
logger.error(__('Invalid <log-server-port> found in the tiapp.xml: %s', logServerPort) + '\n');
process.exit(1);
}

series(this, [
function validateExtensions(next) {
// if there's no extensions, then skip this step
Expand Down Expand Up @@ -2296,6 +2303,7 @@ iOSBuilder.prototype.determineLogServerPort = function determineLogServerPort(ne
server.on('error', function () {
server.close(function () {
// try again
_t.logger.debug(__('Log server port %s is unavailable, selecting a new random port', port));
port = ~~(Math.random() * 1e4) % 50000 + 1e4;
cb();
});
Expand All @@ -2305,6 +2313,7 @@ iOSBuilder.prototype.determineLogServerPort = function determineLogServerPort(ne
port: port
}, function () {
server.close(function () {
_t.logger.debug(__('Log server port %s is available', port));
_t.tiLogServerPort = port;
cb();
});
Expand Down Expand Up @@ -2356,6 +2365,12 @@ iOSBuilder.prototype.loginfo = function loginfo() {
}
}

if (this.tiLogServerPort) {
this.logger.info(__('Logging enabled on port %s', cyan(String(this.tiLogServerPort))));
} else {
this.logger.info(__('Logging disabled'));
}

if (this.debugHost) {
this.logger.info(__('Debugging enabled via debug host: %s', cyan(this.debugHost)));
} else {
Expand Down
62 changes: 52 additions & 10 deletions iphone/cli/hooks/install.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* install.js: Titanium iOS CLI install hook
*
* Copyright (c) 2012-2014, Appcelerator, Inc. All Rights Reserved.
* Copyright (c) 2012-2016, Appcelerator, Inc. All Rights Reserved.
* See the LICENSE file for more information.
*/

Expand Down Expand Up @@ -99,11 +99,23 @@ exports.init = function (logger, config, cli) {
startLog = false,
runningCount = 0,
disconnected = false,
installCount = 0;
installCount = 0,
handles = {};

function quit(force) {
function quit(force, udid) {
running = false;
runningCount--;

if (udid && handles[udid]) {
handles[udid].stop();
delete handles[udid];
} else if (force) {
Object.keys(handles).forEach(function (udid) {
handles[udid].stop();
delete handles[udid];
});
}

if (force || runningCount <= 0) {
if (startLog) {
var endLogTxt = __('End application log');
Expand All @@ -121,7 +133,7 @@ exports.init = function (logger, config, cli) {

logger.info(__('Installing app on device: %s', device.name.cyan));

ioslib.device
var handle = handles[udid] = ioslib.device
.install(udid, builder.xcodeAppDir, {
appName: builder.tiapp.name,
logPort: builder.tiLogServerPort
Expand All @@ -140,15 +152,45 @@ exports.init = function (logger, config, cli) {
next();
})
.on('app-started', function () {
running = true;
runningCount++;
})
.on('log', function (msg) {
var skipLine = false;

if (!handles[udid].logStarted) {
if (msg.indexOf('{') === 0) {
try {
var headers = JSON.parse(msg);
if (headers.appId !== builder.tiapp.id) {
logger.error(__('Tried to connect to app "%s", but connected to another app with id "%s"', builder.tiapp.id, headers.appId));
logger.error(__('It is likely that you have two apps using the same log server port %s', builder.tiLogServerPort));
logger.error(__('Either stop all instances of the other app or explicitly set a unique <log-server-port> in the <ios> section of the tiapp.xml') + '\n');
handle.stop();

running = false;
if (--runningCount <= 0) {
process.exit(1);
}
}
} catch (e) {
// squeltch
}
skipLine = true;
}
handles[udid].logStarted = true;
}

if (!startLog) {
var startLogTxt = __('Start application log');
logger.log(('-- ' + startLogTxt + ' ' + (new Array(75 - startLogTxt.length)).join('-')).grey);
startLog = true;
}
running = true;
runningCount++;
})
.on('log', function (msg) {

if (skipLine) {
return;
}

var m = msg.match(logLevelRE);
if (m) {
var line = m[0].trim();
Expand All @@ -172,8 +214,8 @@ exports.init = function (logger, config, cli) {
}
}
})
.on('app-quit', quit)
.on('disconnect', quit)
.on('app-quit', function () { quit(false, udid); })
.on('disconnect', function () { quit(false, udid); })
.on('error', function (err) {
err = err.message || err.toString();
var details;
Expand Down
22 changes: 22 additions & 0 deletions iphone/cli/hooks/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,32 @@ exports.init = function (logger, config, cli) {
})
.on('log-file', function (line) {
// Titanium app log messages
var skipLine = false;

if (!simStarted) {
if (line.indexOf('{') === 0) {
try {
var headers = JSON.parse(line);
if (headers.appId !== builder.tiapp.id) {
logger.error(__('Tried to connect to app "%s", but connected to another app with id "%s"', builder.tiapp.id, headers.appId));
logger.error(__('It is likely that you have two apps using the same log server port %s', builder.tiLogServerPort));
logger.error(__('Either stop all instances of the other app or explicitly set a unique <log-server-port> in the <ios> section of the tiapp.xml') + '\n');
process.exit(1);
}
} catch (e) {
// squeltch
}
skipLine = true;
}

simStarted = true;
logger.log(('-- ' + startLogTxt + ' ' + (new Array(75 - startLogTxt.length)).join('-')).grey);
}

if (skipLine) {
return;
}

var m = line.match(logLevelRE);
if (m) {
lastLogger = m[2].toLowerCase();
Expand Down
8 changes: 7 additions & 1 deletion node_modules/ioslib/lib/device.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 16 additions & 5 deletions node_modules/ioslib/lib/simulator.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.