Skip to content

Instantly share code, notes, and snippets.

@aboodysa
Created April 1, 2013 23:06
Show Gist options
  • Save aboodysa/5288536 to your computer and use it in GitHub Desktop.
Save aboodysa/5288536 to your computer and use it in GitHub Desktop.
chat hub
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using SimpleChat.Models;
using System.Collections.Concurrent;
namespace SimpleChat
{
[Authorize]
[HubName("chatHub")]
public class ChatHub2 : Hub
{
private static readonly ConcurrentDictionary<string, User> Users
= new ConcurrentDictionary<string, User>(StringComparer.InvariantCultureIgnoreCase);
ChatContext _db = new ChatContext();
public void Send(string message)
{
string sender = Context.User.Identity.Name;
//User sender = Context.User.Identity.Name;
string groupName = GetGroupName(sender);
// So, broadcast the sender, too.
//Clients.OthersInGroup(groupName).received(new { sender = sender, message = message, isPrivate = false });
Clients.Group(groupName).received(new { sender = sender, message = message, isPrivate = false });
//Clients.All.received(new { sender = sender, message = message, isPrivate = false });
}
public void SendMessage(string message)
{
string sender = Context.User.Identity.Name;
//User sender = Context.User.Identity.Name;
string groupName = GetGroupName(sender);
// So, broadcast the sender, too.
//Clients.OthersInGroup(groupName).received(new { sender = sender, message = message, isPrivate = false });
//Clients.Group(groupName).received(new { sender = sender, message = message, isPrivate = false });
Clients.Group(groupName).received(new { sender = sender, message = message, isPrivate = false });
}
public void Send(string message, string to)
{
User receiver;
if (Users.TryGetValue(to, out receiver))
{
User sender = GetUser(Context.User.Identity.Name);
IEnumerable<string> allReceivers;
lock (receiver.ConnectionIds)
{
lock (sender.ConnectionIds)
{
allReceivers = receiver.ConnectionIds.Concat(sender.ConnectionIds);
}
}
foreach (var cid in allReceivers)
{
Clients.Client(cid).received(new { sender = sender.Name, message = message, isPrivate = true });
}
}
}
public void JoinRoom(string room)
{
// NOTE: this is not persisted - ....
Groups.Add(Context.ConnectionId, room);
}
public void SendMessageToRoom(string room, string message)
{
string sender = Context.User.Identity.Name;
//User sender = Context.User.Identity.Name;
string groupName = GetGroupName(sender);
Clients.Group(room).received(new { sender = sender, message = message, isPrivate = false });
}
//public Task<int> SendDataAsync()
//{
// // async ... work...
//}
private String GetGroupName(string userName)
{
return _db.Logins.Single(r => r.Name == userName).GroupName;
}
public override Task OnConnected()
{
string username = Context.User.Identity.Name;
string groupname = this.GetGroupName(username);
Groups.Add(Context.ConnectionId, groupname);
string userName = Context.User.Identity.Name;
string connectionId = Context.ConnectionId;
string groupName = _db.Logins.Single(r => r.Name == userName).GroupName;
var user = Users.GetOrAdd(userName, _ => new User
{
Name = userName,
ConnectionIds = new HashSet<string>(),
GroupName = groupName
});
lock (user.ConnectionIds)
{
user.ConnectionIds.Add(connectionId);
//Groups.Add(connectionId, groupName);
// // broadcast this to all clients other than the caller
// Clients.AllExcept(user.ConnectionIds.ToArray()).userConnected(userName);
// Or you might want to only broadcast this info if this
// is the first connection of the user
if (user.ConnectionIds.Count == 1)
{
Clients.OthersInGroup(groupName).userConnected(userName);
}
}
//SendMonitoringData("Connected", Context.ConnectionId);
return base.OnConnected();
}
public override Task OnDisconnected()
{
string userName = Context.User.Identity.Name;
string connectionId = Context.ConnectionId;
string groupName = GetGroupName(userName);
User user;
Users.TryGetValue(userName, out user);
if (user != null)
{
lock (user.ConnectionIds)
{
foreach (string conId in user.ConnectionIds)
{
Groups.Remove(connectionId, groupName);
}
user.ConnectionIds.RemoveWhere(cid => cid.Equals(connectionId));
if (!user.ConnectionIds.Any())
{
User removedUser;
Users.TryRemove(userName, out removedUser);
// You might want to only broadcast this info if this
// is the last connection of the user and the user actual is
// now disconnected from all connections.
Clients.Group(removedUser.GroupName).userDisconnected(userName);
//Clients.All.userDisconnected(userName);
}
}
}
//SendMonitoringData("Disconnected", Context.ConnectionId);
return base.OnDisconnected();
}
public override Task OnReconnected()
{
//SendMonitoringData("Reconnected", Context.ConnectionId);
return base.OnReconnected();
}
private void SendMonitoringData(string eventType, string connection)
{
var context = GlobalHost.ConnectionManager.GetHubContext<MonitorHub>();
context.Clients.All.newEvent(eventType, connection);
}
protected override void Dispose(bool disposing)
{
_db.Dispose();
base.Dispose(disposing);
}
public IEnumerable<string> GetConnectedUsers()
{
//User sender = GetUser(Context.User.Identity.Name);
var users = Users.Where(x =>
{
lock (x.Value.ConnectionIds)
{
return !x.Value.ConnectionIds.Contains(Context.ConnectionId, StringComparer.InvariantCultureIgnoreCase);
}
});
return users.Where(x =>
{
lock (x.Value.GroupName)
{
return x.Value.GroupName == this.GetGroupName(Context.User.Identity.Name);
}
}).Select(x => x.Key);
}
private User GetUser(string username)
{
User user;
Users.TryGetValue(username, out user);
return user;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment