\feffusing System;\r
using System.Net;\r
+using System.Threading;\r
+using System.Net.Sockets;\r
using Newtonsoft.Json.Linq;\r
\r
using System.Text;\r
-using System.Threading;\r
-using System.Net.Sockets;\r
+using System.Collections.Generic;\r
\r
namespace Stratum\r
{\r
public class Stratum\r
{\r
private Socket client;\r
+ private Dictionary<string, string> responses = new Dictionary<string, string>();\r
+ ManualResetEvent gotResponse = new ManualResetEvent(false);\r
\r
/// <summary>\r
/// Constructor of Stratum interface class\r
ConnectCallback = (IAsyncResult ar) =>\r
{\r
// Retrieve socket from the state object\r
- Socket cli = (Socket)ar.AsyncState;\r
+ Socket arClient = (Socket)ar.AsyncState;\r
\r
// Complete the connection\r
- cli.EndConnect(ar);\r
+ arClient.EndConnect(ar);\r
\r
// Signal that connection has been established\r
connectDone.Set();\r
\r
// Wait for signal\r
connectDone.WaitOne();\r
+\r
+ // Start receive handler\r
+ Receiver(client);\r
}\r
\r
~Stratum()\r
SendCallback = (IAsyncResult ar) =>\r
{\r
// Retrieve the socket from the state object\r
- Socket cli = (Socket)ar.AsyncState;\r
+ Socket arClient = (Socket)ar.AsyncState;\r
\r
// Complete sending the data to the remote device\r
- int bytesSent = cli.EndSend(ar);\r
+ int bytesSent = arClient.EndSend(ar);\r
\r
// Signal that all bytes have been sent\r
sendDone.Set();\r
\r
private StratumResponse<T> Invoke<T>(StratumRequest stratumReq)\r
{\r
- StratumResponse<T> rjson = null;\r
-\r
// Serialize stratumReq into JSON string\r
var reqJSON = Newtonsoft.Json.JsonConvert.SerializeObject(stratumReq) + '\n';\r
+ var reqId = (string) stratumReq.Id;\r
\r
// Send JSON data to the remote device.\r
Send(client, reqJSON);\r
\r
+ // Wait for response\r
+ gotResponse.WaitOne();\r
+\r
+ // Deserialize the response\r
+ string strResponse = responses[reqId];\r
+ StratumResponse<T> responseObj = Newtonsoft.Json.JsonConvert.DeserializeObject<StratumResponse<T>>(strResponse);\r
+ responses.Remove(reqId);\r
+\r
+ // Reset the state\r
+ gotResponse.Reset();\r
+\r
+ if (object.ReferenceEquals(null, responseObj))\r
+ {\r
+ try\r
+ {\r
+ JObject jo = Newtonsoft.Json.JsonConvert.DeserializeObject(strResponse) as JObject;\r
+ throw new Exception(jo["Error"].ToString());\r
+ }\r
+ catch (Newtonsoft.Json.JsonSerializationException)\r
+ {\r
+ throw new Exception("Inconsistent or empty response");\r
+ }\r
+ }\r
+\r
+ return responseObj;\r
+ }\r
+\r
+ private void Receiver(Socket client)\r
+ {\r
// Create the reading state object.\r
StratumReadState state = new StratumReadState(client);\r
\r
- // Receive event\r
- ManualResetEvent receiveDone = new ManualResetEvent(false);\r
-\r
Action<IAsyncResult> ReceiveCallback = null;\r
ReceiveCallback = (IAsyncResult ar) =>\r
{\r
// Retrieve the state object and the client socket \r
// from the asynchronous state object.\r
- StratumReadState st = (StratumReadState)ar.AsyncState;\r
- Socket ci = st.workSocket;\r
+ StratumReadState arStatus = (StratumReadState)ar.AsyncState;\r
+ Socket arClient = arStatus.workSocket;\r
\r
// Read data from the remote device.\r
- int bytesRead = ci.EndReceive(ar);\r
+ int bytesRead = arClient.EndReceive(ar);\r
\r
if (bytesRead <= 0)\r
return;\r
\r
- lock (st.sb)\r
+ lock (arStatus.sb)\r
{\r
// There might be more data, so store the data received so far.\r
- st.sb.Append(Encoding.ASCII.GetString(st.buffer, 0, bytesRead));\r
+ arStatus.sb.Append(Encoding.ASCII.GetString(arStatus.buffer, 0, bytesRead));\r
\r
- if (st.buffer[bytesRead - 1] != '\n')\r
+ if (arStatus.buffer[bytesRead - 1] == '\n')\r
{\r
- // No EOL at the end of buffer, going to get the rest of data\r
- ci.BeginReceive(st.buffer, 0, StratumReadState.BufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), st);\r
- }\r
- else\r
- {\r
- string strResponse = st.sb.ToString();\r
+ string strMessage = arStatus.sb.ToString();\r
+ arStatus.sb.Clear();\r
\r
- // Deserialize the response\r
- rjson = Newtonsoft.Json.JsonConvert.DeserializeObject<StratumResponse<T>>(strResponse);\r
-\r
- if (rjson == null)\r
+ try\r
{\r
- try\r
+ JObject jo = Newtonsoft.Json.JsonConvert.DeserializeObject(strMessage) as JObject;\r
+ string requestId = (string)jo["id"];\r
+\r
+ if (!String.IsNullOrEmpty(requestId))\r
{\r
- JObject jo = Newtonsoft.Json.JsonConvert.DeserializeObject(strResponse) as JObject;\r
- throw new Exception(jo["Error"].ToString());\r
+ responses.Add(requestId, strMessage);\r
+\r
+ gotResponse.Set();\r
}\r
- catch (Newtonsoft.Json.JsonSerializationException)\r
+ else\r
{\r
- throw new Exception("Inconsistent or empty response");\r
+ // TODO: notifications handling\r
+ Console.WriteLine("Notification: {0}", strMessage);\r
}\r
}\r
-\r
- // Signal that all bytes have been received.\r
- receiveDone.Set();\r
+ catch (Newtonsoft.Json.JsonSerializationException e)\r
+ {\r
+ // TODO: handle parse error\r
+ }\r
}\r
}\r
+\r
+ arClient.BeginReceive(arStatus.buffer, 0, StratumReadState.BufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), arStatus);\r
};\r
\r
- // Begin receiving the data from the remote device.\r
client.BeginReceive(state.buffer, 0, StratumReadState.BufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);\r
- receiveDone.WaitOne();\r
-\r
- return rjson;\r
}\r
}\r
+\r
}
\ No newline at end of file