/** * Function to send a message to the server * \param stream - The stream to write to * \param msg - The message to send * \return - Retun true on success, false on failure */ private bool sendMessage(NetworkStream stream, Message msg) { string json = JsonConvert.SerializeObject(msg); using (MemoryStream mstream = new MemoryStream()) { using (BinaryWriter writer = new BinaryWriter(mstream)) { byte[] encodedJson = Encoding.UTF8.GetBytes(json); writer.Write(hostToBig_i32(encodedJson.Length)); writer.Write(encodedJson); } byte[] request = mstream.ToArray(); try { stream.Write(request, 0, request.Length); stream.Flush(); } catch(SocketException ex) { Message emsg = new Message("error_socket", null); emsg.AddParameter("error_code", ex.ErrorCode); emsg.AddParameter("message", ex.Message); recvq.Enqueue(emsg); return false; } } return true; }
/** * Function used to handle messages coming from the GUI client * \param msg - The message to handle */ private void dispatchSendMsg(Message msg) { switch(msg.Command) { case "connect": // Try to connect to server Client = new TcpClient(); string host = msg.Arguments["host"].ToString(); int port = Convert.ToInt32(msg.Arguments["port"]); try { Client.Connect(host, port); } catch(Exception ex) { msg.Command = "connect_failed"; msg.Arguments.Add("message", ex.Message); recvq.Enqueue(msg); return; } if (Client.Connected) { // Store the stream from the TCP client ClientStream = Client.GetStream(); // Empty the network buffer recvBuffer.Clear(); // Update the message to a connection response message and send it back to GUI client msg.Command = "connect_ok"; recvq.Enqueue(msg); } else { msg.Command = "connect_failed"; msg.Arguments.Add("message", "Connection failed"); recvq.Enqueue(msg); } break; case "disconnect": // Disconnect from server and send response back to GUI client if (ClientStream != null) ClientStream.Close(); ClientStream = null; if(Client != null && Client.Connected) Client.Close(); Client = null; msg.Command = "disconnect_ok"; recvq.Enqueue(msg); break; default: if (ClientStream == null) { Message responseMsg = new Message("error", null); responseMsg.AddParameter("message", "Can not send message, not connected to peer"); recvq.Enqueue(responseMsg); return; } // Send message to server if(!sendMessage(ClientStream, msg)) { Message responseMsg = new Message("error", null); responseMsg.AddParameter("message", "Unable to send message"); recvq.Enqueue(responseMsg); return; } break; } }
/** * Function used to handle messages coming from server * \param msg - The message to handle */ private void dispatchRecvMsg(Message msg) { switch (msg.Command) { case "close_ok": // The server has received a close message and are closing down if (ClientStream != null) ClientStream.Close(); ClientStream = null; if(Client != null && Client.Connected) Client.Close(); Client = null; recvq.Enqueue(msg); // Pass message back to GUI client break; default: recvq.Enqueue(msg); // Pass message back to GUI client break; } }
/** * Function to read messages out of the network buffer * \param msg - Storage for any message read from the network buffer * \return - Return true if a complete message was extracted, false if not */ private bool recvMessage(out Message msg) { msg = null; // Make sure buffer hold at least a 32 bit int (netstrings) if (recvBuffer.Count < 4) return false; // Read the message size out of the buffer byte[] byteSize = new byte[4]; recvBuffer.CopyTo(0, byteSize, 0, 4); // Convert the size to the hosts endianness int siz = bigToHost_i32(byteSize); // Make sure the message stored in the buffer are complete if (recvBuffer.Count < 4 + siz) return false; // Read out the message and update the buffer byte[] bjson = new byte[siz]; recvBuffer.CopyTo(4, bjson, 0, siz); recvBuffer.RemoveRange(0, 4 + siz); // Deserialize the message string json = Encoding.UTF8.GetString(bjson); msg = JsonConvert.DeserializeObject<Message>(json); return true; }