static void ClientDisconnected(object sender, EventArgs e) { Debug.WriteLine(DateTime.Now + ": Client disconnect: " + ((IClientChannel)sender).SessionId.ToString()); // cleanup event TEventEntry channelEvent; if (Lookups.channelToEvent.TryGetValue(sender, out channelEvent)) { // decode session part of event name var sessionEventName = channelEvent.eventName.Substring(0, channelEvent.eventName.LastIndexOf('.')); var connection = channelEvent.connection; // signal client is removed channelEvent.signalIntString(TEventEntry.actionDelete, ((IClientChannel)sender).SessionId); // channel, action delete (optional session id) // remove link between channel and event channelEvent.unPublish(); channelEvent.unSubscribe(); channelEvent.Tag = null; Lookups.channelToEvent.Remove(sender); //Lookups.channelToClientType.Remove(sender); //Lookups.channelToRemoteAddress.Remove(sender); lock (Lookups.rootEvent) { // check if last channel on session then session can be discarded if (Lookups.checkForLastChannel(sessionEventName + ".")) { var sessionEvent = connection.publish(sessionEventName, false); // already published so is just a lookup // remove handler sessionEvent.onIntString -= SessionEvent_onIntString; // unlink sessionEvent.unPublish(); sessionEvent.unSubscribe(); Debug.WriteLine(" Last client on session " + sessionEventName); } } } }
public void SendMessageToServer(Message msg) { try { var callback = OperationContext.Current.GetCallbackChannel <IMessageToClient>(); var channel = OperationContext.Current.Channel; TEventEntry channelEvent; if (!Lookups.channelToEvent.TryGetValue(channel, out channelEvent)) { var queryParameters = HttpUtility.ParseQueryString((OperationContext.Current.IncomingMessageProperties["WebSocketMessageProperty"] as WebSocketMessageProperty).WebSocketContext.RequestUri.Query); var sessionName = queryParameters["session"]; string clientType = ""; try { clientType = queryParameters["clienttype"]; } catch { } if (sessionName == null || sessionName == "") { sessionName = "unknown"; } //var remoteAddress = OperationContext.Current.IncomingMessageHeaders.From; var repmp = OperationContext.Current.IncomingMessageProperties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty; var remoteAddress = repmp.Address + ":" + repmp.Port.ToString(); // signal start of client on session Debug.WriteLine(DateTime.Now + ": Start of client " + remoteAddress + " on session: " + sessionName + " (" + channel.SessionId.ToString() + ", " + clientType + ")"); try { Lookups.channelToClientType[channel] = clientType; Lookups.channelToRemoteAddress[channel] = remoteAddress; var sessionEvent = Lookups.connection.publish(Lookups.RootEventName + "." + sessionName, false); // make sure we have a root event Lookups.HookupRoot(); // check if first channel on session lock (Lookups.rootEvent) { if (!sessionEvent.isSubscribed) { // yes, is the first channel on session Debug.WriteLine(" First client on session " + sessionEvent.eventName); sessionEvent.subscribe(); // make client list queryable by session module sessionEvent.onIntString += ClientTrackerChannelInitializer.SessionEvent_onIntString; } } // setup channel channelEvent = Lookups.connection.subscribe(sessionEvent.eventName + "." + channel.SessionId, false); Lookups.channelToEvent[channel] = channelEvent; channelEvent.Tag = callback; channelEvent.onString += ChannelEvent_onString; channelEvent.onStreamCreate += ChannelEvent_onStreamCreate; channelEvent.onStreamEnd += ChannelEvent_onStreamEnd; // make client event manageable by session module channelEvent.onIntString += ChannelEvent_onIntString; // new channel with event name on session event string channelEventNamePostfix; try { channelEventNamePostfix = (clientType != null) && (clientType.Length > 0) ? "&" + clientType : ""; } catch { channelEventNamePostfix = ""; } sessionEvent.signalIntString(TEventEntry.actionNew, channelEvent.eventName + channelEventNamePostfix); // todo: signal new client on root event? } catch (Exception e) { Debug.WriteLine(DateTime.Now + ": ## exception registering channel: " + e.Message); } } if (!msg.IsEmpty && ((IChannel)callback).State == CommunicationState.Opened) { byte[] returnMessage = msg.GetBody <byte[]>(); if (returnMessage.Length > TConnection.imbMaximumPayloadSize / 10) // switch to stream for very large messages { channelEvent.signalStream("string", new MemoryStream(returnMessage)); } else { channelEvent.signalString(returnMessage); } } } catch (Exception e) { Debug.WriteLine(DateTime.Now + ": ## unhandled exception in WebSocketsServer.SendMessageToServer: " + e.Message); } }