Ejemplo n.º 1
0
        private byte[] GetWebsocketMessageData(WebsocketPipeMessageInfo msg)
        {
            MemoryStream strm = new MemoryStream();

            System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
            watch.Start();
            try
            {
                DataSocket.WriteMessage(msg, strm);
            }
            catch (Exception ex)
            {
                var str = "Error while writing to data socket: " + ex.Message;
                WriteLogMessage(null, str);
                throw new Exception(str, ex);
            }

            watch.Stop();
            WriteLogTimeMessage(null, "Write to datasocket, ", watch.Elapsed.TotalMilliseconds);

            byte[] data = strm.ToArray();
            strm.Close();
            strm.Dispose();
            return(data);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Writes the message to a memory mapped file, where the memory mapped file name is WebsocketPipe.Address + id.
        /// mmf format: [wasread? 1 byte][datasize(int)][length(int)][msg][length(int)][msg]...
        /// If wasread=0, then writes the new message to the end of the message list and advances the number of messages +1.
        /// If wasread=1, clears the mmf and then writes the new message.
        /// </summary>
        /// <param name="wp">The calling WebsocketPipe</param>
        /// <param name="msg">The message to write.</param>
        /// <param name="to">The stream to write the mmf filename to.</param>
        /// <param name="id">The id of the targer we are writing to, since there may be many we open a mmf for each</param>
        public virtual void WriteMessage(WebsocketPipeMessageInfo msg, Stream to)
        {
            if (msg.Data.Length < this.UseInternalPacketDataSendingIfMsgByteSizeIsLessThen)
            {
                // write that this is an internal message.
                to.WriteByte(1);
                WebsocketAsInternalDataSocket.WriteMessage(msg, to);
                return;
            }

            // write that this is a mmf msg.
            to.WriteByte(0);

            // make the id and write it to the stream.
            string id = MakeValidMmfID(msg.DataSocketId);

            byte[] mmfnamebuffer = ASCIIEncoding.ASCII.GetBytes(id);
            to.Write(mmfnamebuffer, 0, mmfnamebuffer.Length);

            Mutex mu = new Mutex(false, id + "_mutex");

            if (!mu.WaitOne(MemoryMappedFileAccessTimeout))
            {
                throw new Exception("Memory mapped file access timedout.");
            }

            // The data size for a single message.
            int totalDataSize = msg.Data.Length + sizeof(int) + 1;

            // Creating/Opening the stream.
            MemoryMappedViewStream strm = GetDataWritingMemoryMappedViewStream(id, ref totalDataSize);

            // we are at the position of the write, and are ready for the message write.
            msg.WriteToStream(strm);

            strm.Flush();
            strm.Close();
            strm.Dispose();
            strm = null;

            // release the mutex.
            mu.ReleaseMutex();
        }
Ejemplo n.º 3
0
 public virtual IEnumerable <WebsocketPipeMessageInfo> ReadMessages(Stream from)
 {
     return(new WebsocketPipeMessageInfo[] { WebsocketPipeMessageInfo.FromStream(from) });
 }
Ejemplo n.º 4
0
 public virtual void WriteMessage(WebsocketPipeMessageInfo msg, Stream to)
 {
     msg.WriteToStream(to);
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Reads the pending messages in the memory mapped file, where the memory mapped file name is in the stream from.
        /// mmf format: [wasread? 1 byte][datasize(int)][length(int)][msg][length(int)][msg]...
        /// If wasread=1, then ignores the read since the mmf was not written to, or was already read.
        /// If wasread=0, reads all pending messages and sets wasread to 1.
        /// </summary>
        /// <param name="wp"></param>
        /// <param name="from"></param>
        /// <returns></returns>
        public virtual IEnumerable <WebsocketPipeMessageInfo> ReadMessages(Stream from)
        {
            // reading the memory mapped file name or the msg bytes.
            if (from.ReadByte() == 1)
            {
                // internal message.
                return(WebsocketAsInternalDataSocket.ReadMessages(from));
            }

            // read the id from the from stram.
            StreamReader freader = new StreamReader(from, ASCIIEncoding.ASCII);
            string       id      = freader.ReadToEnd();

            // calling the mutex to verify reading.
            Mutex mu = new Mutex(false, id + "_mutex");

            if (!mu.WaitOne(MemoryMappedFileAccessTimeout))
            {
                throw new Exception("Wait timeout while attempting to read messages from mmf file with id: " + id);
            }

            MemoryMappedFile mmf    = MemoryMappedFile.OpenExisting(id);
            Stream           strm   = mmf.CreateViewStream(0, 0, MemoryMappedFileAccess.ReadWrite);
            BinaryReader     reader = new BinaryReader(strm);

            strm.Seek(0, SeekOrigin.Begin);

            BinaryReader msgreader       = null;
            int          totalDataLength = 0;

            if (strm.Length > MMFHeaderSize && reader.ReadByte() == 0)
            {
                // there is something we need to read.
                // reading all the contents.
                totalDataLength = reader.ReadInt32();

                if (totalDataLength > 0)
                {
                    msgreader = new BinaryReader(new MemoryStream(reader.ReadBytes(totalDataLength)));
                }

                // marking as read.
                strm.Seek(0, SeekOrigin.Begin);
                strm.WriteByte(1);
            }

            strm.Flush();
            strm.Close();
            strm.Dispose();

            // clearing the newly created mmf.
            mmf.Dispose();
            mmf = null;

            // release the mutex allowing others to write.
            mu.ReleaseMutex();
            mu.Dispose();
            mu     = null;
            reader = null;

            // return nothing...
            if (msgreader == null)
            {
                return(new WebsocketPipeMessageInfo[0]);
            }

            // reading the messages.
            strm = msgreader.BaseStream;
            msgreader.BaseStream.Seek(0, SeekOrigin.Begin);

            List <WebsocketPipeMessageInfo> msgs = new List <WebsocketPipeMessageInfo>();

            while (strm.Position < totalDataLength)
            {
                WebsocketPipeMessageInfo info = WebsocketPipeMessageInfo.FromStream(msgreader);
                if (info == null)
                {
                    break;  // something went wrong.
                }
                msgs.Add(info);
            }

            strm.Close();
            strm.Dispose();
            msgreader = null;
            strm      = null;
            return(msgs);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Sends a message to sepcific clients by the client id. Method should be used for servers.
        /// </summary>
        /// <param name="msg">The message to send</param>
        /// <param name="clientIds">The client ids to send the msg to, if a server.</param>
        /// /// <param name="response">If not null, the thread will wait for response.</param>
        public void Send(TMessage msg, string[] clientIds, Action <TMessage> response = null)
        {
            //if (clientIds != null && WS != null)
            //    throw new Exception("You are trying to send a message to specific clients from a client WebsocketPipe. This is not A server.");
            if (WSServer == null && WS == null)
            {
                throw new Exception("Not connected to any server or listening for connections. Please call either Connect, or Listen.");
            }

            Stopwatch watch = new Stopwatch();
            WebsocketPipeMessageInfo minfo;

            watch.Start();
            try
            {
                minfo = new WebsocketPipeMessageInfo(Serializer.ToBytes <TMessage>(msg), null, response != null);
            }
            catch (Exception ex)
            {
                var str = "Error serializing message. " + ex.Message;
                WriteLogMessage(null, str);
                throw new Exception(str, ex);
            }

            watch.Stop();

            WriteLogTimeMessage(null, "Serialized msg with " + minfo.Data.Length + " [bytes]", watch.Elapsed.TotalMilliseconds);
            var senders = new[] { new
                                  {
                                      socketID  = "",
                                      handlerID = "",
                                      session   = (WebSocket)null,
                                      hndl      = (ResponseWaitHandle)null,
                                  } }.ToList(); senders.Clear();


            if (WS != null)
            {
                senders.Add(new
                {
                    socketID  = ToDataSocketID(SendAsClientWebsocketID),
                    handlerID = SendAsClientWebsocketID,
                    session   = WS,
                    hndl      = new ResponseWaitHandle(),
                });
            }
            else
            {
                foreach (WebSocketSharp.Server.IWebSocketSession session in FindValidSession(clientIds))
                {
                    senders.Add(new
                    {
                        socketID  = ToDataSocketID(session.ID),
                        handlerID = session.ID,
                        session   = session.Context.WebSocket,
                        hndl      = new ResponseWaitHandle(),
                    });
                }
            }

            if (senders.Count == 0)
            {
                if (response != null)
                {
                    response(null);
                }
                return; // nothing to do.
            }

            if (response == null)
            {
                foreach (var sender in senders)
                {
                    minfo.DataSocketId = sender.socketID;
                    sender.session.Send(GetWebsocketMessageData(minfo));
                    //sender.session.SendAsync(GetWebsocketMessageData(minfo), (t) => { });
                }
            }
            else
            {
                foreach (var sender in senders)
                {
                    PendingResponseWaitHandles[sender.socketID] = sender.hndl;
                }

                foreach (var sender in senders)
                {
                    minfo.DataSocketId = sender.socketID;
                    sender.session.Send(GetWebsocketMessageData(minfo));
                    //sender.session.SendAsync(GetWebsocketMessageData(minfo), (t) =>
                    //{
                    //    if (!t)
                    //    {
                    //        // not complete sending.
                    //        // error.
                    //        // response is null.
                    //        sender.hndl.Response = null;
                    //        sender.hndl.Set();
                    //    }
                    //});
                }

                bool timedout = false;
                foreach (var sender in senders)
                {
                    if (!sender.hndl.WaitOne(WaitTimeout))
                    {
                        timedout = true;
                    }
                }

                // check if timeout.
                //bool timedout = senders.Any(s => s.hndl.WaitOne(0));

                if (timedout)
                {
                    throw new Exception("Timedout waiting for response. Waited [ms] " + WaitTimeout.TotalMilliseconds);
                }

                foreach (var sender in senders)
                {
                    response(sender.hndl.Response);
                }
            }
        }