Merge branch 'develop' into feature/sprint_12_work

This commit is contained in:
Brian Smith 2014-09-28 12:00:32 -04:00
commit a07fdfe2a8
16 changed files with 87 additions and 32 deletions

View File

@ -671,6 +671,7 @@ message ServerGenericError {
// but gives the client a chance to know why.
message ServerRejectionError {
optional string error_msg = 1;
optional string error_code = 2;
}
// route_to: client

View File

@ -197,8 +197,8 @@ module JamRuby
end
# create a server rejection error
def server_rejection_error(error_msg)
error = Jampb::ServerRejectionError.new(:error_msg => error_msg)
def server_rejection_error(error_msg, error_code)
error = Jampb::ServerRejectionError.new(:error_msg => error_msg, :error_code => error_code)
Jampb::ClientMessage.new(
:type => ClientMessage::Type::SERVER_REJECTION_ERROR,

View File

@ -1023,6 +1023,11 @@ module JamRuby
return
end
if connection.locidispid.nil?
@@log.warn("no locidispid for connection's ip_address: #{connection.ip_address}")
return
end
# we don't use a websocket login to update the user's record unless there is no addr
if reason == JAM_REASON_LOGIN && last_jam_addr
return

View File

@ -51,6 +51,7 @@
var $messageContents = null;
var $dialog = null;
var $templateServerConnection = null;
var $templateNoLogin = null;
var $templateDisconnected = null;
var $currentDisplay = null;
@ -109,8 +110,10 @@
// we don't show any reconnect dialog on the initial connect; so we have this one-time flag
// to cause reconnects in the case that the websocket is down on the initially connect
if (!server.noReconnect &&
(initialConnectAttempt || !server.reconnecting)) {
if(server.noReconnect) {
renderLoginRequired();
}
else if ((initialConnectAttempt || !server.reconnecting)) {
server.reconnecting = true;
initialConnectAttempt = false;
@ -272,9 +275,13 @@
function serverRejection(header, payload) {
logger.warn("server rejected our websocket connection. reason=" + payload.error_msg)
if(payload.error_msg == 'max_user_connections') {
if(payload.error_code == 'max_user_connections') {
context.JK.Banner.showAlert("Too Many Connections", "You have too many connections to the server. If you believe this is in error, please contact support.")
}
else if(payload.error_code == 'invalid_login' || payload.error_code == 'empty_login') {
logger.debug(payload.error_code + ": no longer reconnecting")
server.noReconnect = true; // stop trying to log in!!
}
}
///////////////////
@ -330,6 +337,23 @@
return {};
}
function renderLoginRequired() {
var $inSituContent = $(context._.template($templateNoLogin.html(), buildOptions(), { variable: 'data' }));
$inSituContent.find('a.disconnected-login').click(function() {
var redirectPath= '?redirect-to=' + encodeURIComponent(context.JK.locationPath());
if(gon.isNativeClient) {
window.location.href = '/signin' + redirectPath;
}
else {
window.location.href = '/' + redirectPath;
}
return false;
})
$messageContents.empty();
$messageContents.append($inSituContent);
$inSituBannerHolder.addClass('active');
return $inSituBannerHolder;
}
function renderDisconnected() {
var content = null;
@ -523,13 +547,22 @@
connectDeferred = new $.Deferred();
channelId = context.JK.generateUUID(); // create a new channel ID for every websocket connection
var rememberToken = $.cookie("remember_token");
if(isClientMode() && !rememberToken) {
server.noReconnect = true;
logger.debug("no login info; shutting down websocket");
renderLoginRequired();
connectDeferred.reject();
return connectDeferred;
}
// we will log in one of 3 ways:
// browser: use session cookie, and auth with token
// native: use session cookie, and use the token
// latency_tester: ask for client ID from backend; no token (trusted)
var params = {
channel_id: channelId,
token: $.cookie("remember_token"),
token: rememberToken,
client_type: isClientMode() ? context.JK.clientType() : 'latency_tester',
client_id: isClientMode() ? (gon.global.env == "development" ? $.cookie('client_id') : null): context.jamClient.clientID,
os: context.JK.GetOSAsString(),
@ -725,6 +758,7 @@
$messageContents = $inSituBannerHolder.find('.message-contents');
$dialog = $('#banner');
$templateServerConnection = $('#template-server-connection');
$templateNoLogin = $('#template-no-login');
$templateDisconnected = $('#template-disconnected');
if ($inSituBanner.length != 1) {

View File

@ -45,7 +45,7 @@
}
}
.reconnect-progress-msg {
.reconnect-progress-msg, .login-back-in-msg {
margin-bottom:10px;
}

View File

@ -9,4 +9,9 @@
%div.reconnect-progress-msg
%span.reconnect-before= 'Reconnecting automatically in '
%span.reconnect-countdown= '{{data.countdown}}'
%a.disconnected-reconnect.reconnect-enabled{href:'#'} RECONNECT NOW
%a.disconnected-reconnect.reconnect-enabled{href:'#'} RECONNECT NOW
%script{type: 'text/template', id: 'template-no-login'}
%div
%div.login-back-in-msg
%span= 'You will need to log back in'
%a.disconnected-login{href:'#'} GO TO SIGN IN

View File

@ -120,7 +120,7 @@
console.log("websocket connected")
})
.fail(function() {
console.log("websocket failed to connect")
//console.log("websocket failed to connect")
});
})
</script>

View File

@ -18,9 +18,9 @@
<% if Rails.env == "development" %>
ga('create', '<%= Rails.application.config.ga_ua %>', { 'cookieDomain': 'none' });
<% else %>
ga('create', '<%= Rails.application.config.ga_ua %>', 'jamkazam.com');
ga('create', '<%= Rails.application.config.ga_ua %>', 'jamkazam.com');
<% end %>
ga('require', 'displayfeatures');
ga('send', 'pageview', {
dimension1: '<%= ga_user_level %>',
dimension2: '<%= ga_user_type %>'

View File

@ -47,7 +47,7 @@ SampleApp::Application.configure do
OmniAuth.config.test_mode = true
config.websocket_gateway_enable = false
config.websocket_gateway_port = 6769
config.websocket_gateway_port = 6759
config.websocket_gateway_uri = "ws://localhost:#{config.websocket_gateway_port}/websocket"
config.websocket_gateway_connect_time_stale_client = 4

View File

@ -76,7 +76,7 @@ Thread.new do
require 'jam_websockets'
begin
JamWebsockets::Server.new.run(
:port => 6769,
:port => 6759,
:emwebsocket_debug => false,
:connect_time_stale_client => 4,
:connect_time_expire_client => 6,

View File

@ -15,7 +15,7 @@ development:
<<: *defaults
test:
port: 6769
port: 6759
verbose: true
rabbitmq_host: localhost
rabbitmq_port: 5672

View File

@ -245,7 +245,7 @@ module JamWebsockets
@log.info "ending client session deliberately due to malformed client behavior. reason=#{e}"
begin
# wrap the message up and send it down
error_msg = @message_factory.server_rejection_error(e.to_s)
error_msg = @message_factory.server_rejection_error(e.to_s, e.error_code)
send_to_client(client, error_msg)
ensure
cleanup_client(client)
@ -277,6 +277,7 @@ module JamWebsockets
client.trusted = is_trusted
client.onopen { |handshake|
# a unique ID for this TCP connection, to aid in debugging
client.channel_id = handshake.query["channel_id"]
@ -291,7 +292,7 @@ module JamWebsockets
end
websocket_comm(client, nil) do
handle_login(client, handshake.query)
handle_login(client, handshake.query, handshake.headers["X-Forwarded-For"])
end
}
@ -472,10 +473,10 @@ module JamWebsockets
context
end
def handle_latency_tester_login(client_id, client_type, client)
def handle_latency_tester_login(client_id, client_type, client, override_ip)
# respond with LOGIN_ACK to let client know it was successful
remote_ip = extract_ip(client)
remote_ip = extract_ip(client, override_ip)
heartbeat_interval, connection_stale_time, connection_expire_time = determine_connection_times(nil, client_type)
latency_tester = LatencyTester.connect({
client_id: client_id,
@ -511,7 +512,7 @@ module JamWebsockets
end
end
def handle_login(client, options)
def handle_login(client, options, override_ip = nil)
username = options["username"]
password = options["password"]
token = options["token"]
@ -524,7 +525,7 @@ module JamWebsockets
@log.info("handle_login: client_type=#{client_type} token=#{token} client_id=#{client_id} channel_id=#{client.channel_id} udp_reachable=#{udp_reachable}")
if client_type == Connection::TYPE_LATENCY_TESTER
handle_latency_tester_login(client_id, client_type, client)
handle_latency_tester_login(client_id, client_type, client, override_ip)
return
end
@ -541,7 +542,7 @@ module JamWebsockets
# protect against this user swamping the server
if user && Connection.where(user_id: user.id).count >= @max_connections_per_user
@log.warn "user #{user.id}/#{user.email} unable to connect due to max_connections_per_user #{@max_connections_per_user}"
raise SessionError, 'max_user_connections'
raise SessionError, 'max_user_connections', 'max_user_connections'
end
# XXX This logic needs to instead be handled by a broadcast out to all websockets indicating dup
@ -569,7 +570,7 @@ module JamWebsockets
client.client_id = client_id
client.user_id = user.id if user
remote_ip = extract_ip(client)
remote_ip = extract_ip(client, override_ip)
if user
@ -650,7 +651,7 @@ module JamWebsockets
send_to_client(client, login_ack)
end
else
raise SessionError, 'invalid login'
raise SessionError.new('invalid login', 'invalid_login')
end
end
@ -766,7 +767,7 @@ module JamWebsockets
return nil
end
else
raise SessionError, 'no login data was found in Login message'
raise SessionError.new('no login data was found in Login message', 'empty_login')
end
end
@ -882,8 +883,8 @@ module JamWebsockets
end
end
def extract_ip(client)
Socket.unpack_sockaddr_in(client.get_peername)[1]
def extract_ip(client, override_ip)
override_ip || Socket.unpack_sockaddr_in(client.get_peername)[1]
end
def periodical_flag_connections

View File

@ -27,7 +27,7 @@ module JamWebsockets
calling_thread = options[:calling_thread]
trust_check = TrustCheck.new(trust_port, options[:cidr])
@log.info "starting server #{host}:#{port} staleness_time=#{connect_time_stale_client}; reconnect time = #{connect_time_expire_client}, rabbitmq=#{rabbitmq_host}:#{rabbitmq_port}"
@log.info "starting server #{host}:#{port} staleness_time=#{connect_time_stale_client}; reconnect time = #{connect_time_expire_client}, rabbitmq=#{rabbitmq_host}:#{rabbitmq_port} gateway_name=#{gateway_name}"
EventMachine.error_handler{|e|
@log.error "unhandled error #{e}"

View File

@ -1,4 +1,11 @@
class SessionError < Exception
class SessionError < StandardError
attr_accessor :error_code
def initialize(msg, error_code = nil)
super(msg)
@error_code = error_code
end
end

View File

@ -24,7 +24,7 @@ main()
# and bundle won't run because it thinks it has the wrong versions of gems
rm -f Gemfile.lock
JAM_INSTANCE=$JAM_INSTANCE BUILD_NUMBER=$BUILD_NUMBER JAMENV=production exec bundle exec ruby -Ilib bin/websocket_gateway
GATEWAY_NAME="$GATEWAY_NAME" JAM_INSTANCE=$JAM_INSTANCE BUILD_NUMBER=$BUILD_NUMBER JAMENV=production exec bundle exec ruby -Ilib bin/websocket_gateway
}
[ "$#" -ne 1 ] && ( usage && exit 1 ) || main

View File

@ -51,7 +51,7 @@ def login(router, user, password, client_id, token, client_type)
args[0].should == client
args[1].is_a?(Jampb::ClientMessage).should be_true
end
router.should_receive(:extract_ip).at_least(:once).with(client).and_return("127.0.0.1")
router.should_receive(:extract_ip).at_least(:once).with(client, nil).and_return("127.0.0.1")
client.should_receive(:onclose)
client.should_receive(:onerror)
@ -61,6 +61,7 @@ def login(router, user, password, client_id, token, client_type)
@router.new_client(client, false)
handshake = double("handshake")
handshake.should_receive(:query).exactly(3).times.and_return({ "pb" => "true", "channel_id" => SecureRandom.uuid, "client_id" => client_id, "token" => token, "client_type" => client_type })
handshake.should_receive(:headers).at_least(:once).and_return({})
client.onopenblock.call handshake
client
@ -84,7 +85,7 @@ def login_latency_tester(router, latency_tester, client_id)
args[0].should == client
args[1].is_a?(Jampb::ClientMessage).should be_true
end
router.should_receive(:extract_ip).at_least(:once).with(client).and_return("127.0.0.1")
router.should_receive(:extract_ip).at_least(:once).with(client, nil).and_return("127.0.0.1")
client.should_receive(:onclose)
client.should_receive(:onerror)
@ -93,6 +94,7 @@ def login_latency_tester(router, latency_tester, client_id)
@router.new_client(client, true)
handshake = double("handshake")
handshake.should_receive(:query).exactly(3).times.and_return({ "pb" => "true", "channel_id" => SecureRandom.uuid, "client_type" => "latency_tester", "client_id" => client_id })
handshake.should_receive(:headers).at_least(:once).and_return({})
client.onopenblock.call handshake
client
@ -240,7 +242,7 @@ describe Router do
client = TestClient.new
error_msg = message_factory.server_rejection_error("invalid login")
error_msg = message_factory.server_rejection_error("invalid login", "invalid_login")
@router.should_receive(:send_to_client).with(client, error_msg)
client.should_receive(:close_websocket)