// Sending a Payload from server to client expecting an answer, server initiated the request public NewPayLoad SendPayLoad(Guid sessionID, NewPayLoad pL) { GingerSocketInfo c = (from x in Clients where x.SessionID == sessionID select x).SingleOrDefault(); if (c == null) { throw new InvalidOperationException("SendPayLoad, SessionId not found: " + sessionID); } pL.PaylodType = NewPayLoad.ePaylodType.RequestPayload; return(c.SendRequest(pL)); }
// Internal socket communication is handled here private void SocketRequestHandler(GingerSocketInfo gingerSocketInfo) { NewPayLoad Req = gingerSocketInfo.DataAsPayload; if (Req.Name == "GetSession") { gingerSocketInfo.Response = new NewPayLoad("SessionID", SessionID); gingerSocketInfo.Response.PaylodType = NewPayLoad.ePaylodType.SocketResponse; return; } throw new Exception("SocketRequestHandler - Unknown Request: " + Req.Name); }
public void Connect(string IP, int port) { try { //Local host IPAddress ipAddress = IPAddress.Parse(IP); IPEndPoint remoteEP = new IPEndPoint(ipAddress, port); Socket socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); // Connect to Ginger Server async socket.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), socket); mConnectDone.WaitOne(); //start waiting for incoming data async - non blocking // Create the state object. mGingerSocketInfo = new GingerSocketInfo(); mGingerSocketInfo.Socket = socket; mGingerSocketInfo.MessageHandler = MessageHandler; mGingerSocketInfo.Receive(); // Now Ginger client is ready for incoming data mConnected = true; // if there is code here it will run - no wait //TODO: handshake: version, security, encryption NewPayLoad HandShake1 = new NewPayLoad("GetSession", "v1"); HandShake1.PaylodType = NewPayLoad.ePaylodType.SocketRequest; NewPayLoad RC = SendSocketPayLoad(HandShake1); if (RC.Name == "SessionID") { mGingerSocketInfo.SessionID = RC.GetGuid(); } else { throw new Exception("Error in connecting to GingerSocketServer invalid Session"); } } catch (Exception e) { Console.WriteLine("Error: " + e.Message); throw e; } }
// New incoming Ginger Client public void AcceptCallback(IAsyncResult ar) { // Signal the main thread to continue. allDone.Set(); // Get the socket that handles the client request. Socket listener = (Socket)ar.AsyncState; Socket socket = listener.EndAccept(ar); // Create the state object - one per Ginger client GingerSocketInfo gingerSocketInfo = new GingerSocketInfo(); gingerSocketInfo.Socket = socket; gingerSocketInfo.SessionID = Guid.NewGuid(); // Create new session id gingerSocketInfo.MessageHandler = MessageHandler; gingerSocketInfo.Receive(); Clients.Add(gingerSocketInfo); }
// Internal socket communication is handled here private void SocketRequestHandler(GingerSocketInfo gingerSocketInfo) { NewPayLoad Req = gingerSocketInfo.DataAsPayload; if (Req.Name == "GetSession") { gingerSocketInfo.Response = new NewPayLoad("SessionID", SessionID); gingerSocketInfo.Response.PaylodType = NewPayLoad.ePaylodType.SocketResponse; return; } if (Req.Name == "NodeClosing") { gingerSocketInfo.Response = new NewPayLoad("OK", "Bye"); gingerSocketInfo.Response.PaylodType = NewPayLoad.ePaylodType.SocketResponse; // TODO: close... return; } throw new InvalidOperationException("SocketRequestHandler - Unknown Request: " + Req.Name); }
private void MessageHandler(GingerSocketInfo obj) { //TODO: handle request from server throw new NotImplementedException(); }
// Each time new data arrive we get callback private void ReceiveCallback(IAsyncResult ar) { Console.WriteLine("ReceiveCallback"); while (mProcessingStatus == eProcessingStatus.SendingRequest) { Thread.Sleep(1); } try { // Retrieve the state object and the socket // from the asynchronous state object. GingerSocketInfo gingerSocketInfo = (GingerSocketInfo)ar.AsyncState; Socket socket = gingerSocketInfo.Socket; // Read data from the socket int bytesRead = socket.EndReceive(ar); BytesIn += bytesRead; if (bytesRead > 0) { if (gingerSocketInfo.BufferPOS == 0) // do only once per Payload { //TODO: There might be more data, so store the data received so far - need to veruf completion, create TC !! byte[] rcvLenBytesBB = gingerSocketInfo.buffer; // TODO: !!!!!!!!!!!!!temp do work direct - avoid creating a new byte array PayloadLen = ((rcvLenBytesBB[0]) << 24) + (rcvLenBytesBB[1] << 16) + (rcvLenBytesBB[2] << 8) + rcvLenBytesBB[3]; if (PayloadLen > gingerSocketInfo.buffer.Length) { Array.Resize(ref gingerSocketInfo.buffer, PayloadLen + 4); // Make sure we will have enough space // Add 1024 !!! // TODO: check if buffer is more than x size release it back.... } } gingerSocketInfo.BufferPOS += bytesRead; if (gingerSocketInfo.BufferPOS == PayloadLen + 4) { NewPayLoad Resp = new NewPayLoad(gingerSocketInfo.buffer, true); // We got the full packet, convert to Payload and process if (Resp.PaylodType == NewPayLoad.ePaylodType.ResponsePayload || Resp.PaylodType == NewPayLoad.ePaylodType.SocketResponse) { mProcessingStatus = eProcessingStatus.ResponseStarted; // Create new Payload from the buffer, ignoring the extra space at the end Response = new NewPayLoad(gingerSocketInfo.buffer, true); mProcessingStatus = eProcessingStatus.ResponseCompleted; // we are done with pair of Req/Resp - good job - mission completed // signal receive is complete so ready for processing mRequestProcessingDone.Set(); // !!! } else // this is new request, we need to process and respond { IncomingRequetsesCounter++; mProcessingStatus = eProcessingStatus.ProcessingRequest; // This is a request need to respond switch (Resp.PaylodType) { case NewPayLoad.ePaylodType.RequestPayload: MessageHandler(gingerSocketInfo); gingerSocketInfo.Response.PaylodType = NewPayLoad.ePaylodType.ResponsePayload; break; case NewPayLoad.ePaylodType.SocketRequest: SocketRequestHandler(gingerSocketInfo); break; default: throw new Exception("Unknown Payload Type, Payload.Name: " + Resp.Name); } mProcessingStatus = eProcessingStatus.SendingResponse; byte[] bb = gingerSocketInfo.Response.GetPackage(); bytesOut += bb.Length; mSocket.BeginSend(bb, 0, bb.Length, SocketFlags.None, SendCallback, this); mSendDone.WaitOne(); } gingerSocketInfo.BufferPOS = 0; // be ready to accept more new request or incoming data socket.BeginReceive(gingerSocketInfo.buffer, 0, gingerSocketInfo.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), gingerSocketInfo); mProcessingStatus = eProcessingStatus.Ready; } else { // we got a big package more than 1024, starting collecting the bytes until all received socket.BeginReceive(gingerSocketInfo.buffer, gingerSocketInfo.BufferPOS, gingerSocketInfo.buffer.Length - gingerSocketInfo.BufferPOS, SocketFlags.None, new AsyncCallback(ReceiveCallback), gingerSocketInfo); } } else { // All the data has arrived; put it in response. // ???????????????????????????????????????????????????????????????????? // Signal that all bytes have been received. mRequestProcessingDone.Set(); //move up like server ??? } } catch (SocketException e) { if (e.SocketErrorCode == SocketError.ConnectionReset) { Console.WriteLine("SocketException: " + e.Message); //TODO: raise event // other side closed connection - mark socket as dead TODO !!!!!!!!!!!!!!!!!!!!!!! return; } throw e; } catch (Exception ex) { throw ex; } }
/// <summary> /// Connect to Services Grid /// Retry mechanism will retry every 5 seconds up to total 30 seconds /// </summary> /// <param name="IP"></param> /// <param name="port"></param> public void Connect(string IP, int port) { try { //Local host IPAddress ipAddress = IPAddress.Parse(IP); IPEndPoint remoteIP = new IPEndPoint(ipAddress, port); Socket socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); Console.WriteLine("Connecting to: " + remoteIP + ":" + port); // Connect to Ginger Server async, retry max 30 seconds Stopwatch stopwatch = Stopwatch.StartNew(); int retrycount = 0; while (!socket.Connected && stopwatch.ElapsedMilliseconds < 30000) { socket.BeginConnect(remoteIP, new AsyncCallback(ConnectCallback), socket); mConnectDone.WaitOne(); if (!socket.Connected) { retrycount++; Console.WriteLine("Connect retry #" + retrycount); Thread.Sleep(5000); } } if (socket.Connected) { // Now Ginger client is ready for incoming data mConnected = true; } else { Console.WriteLine("Failed to connect, exiting"); mConnected = false; return; } //start waiting for incoming data async - non blocking // Create the state object. mGingerSocketInfo = new GingerSocketInfo(); mGingerSocketInfo.Socket = socket; mGingerSocketInfo.MessageHandler = MessageHandler; mGingerSocketInfo.Receive(); // not blocking // if there is code here it will run - no wait //TODO: handshake: version, security, encryption NewPayLoad HandShake1 = new NewPayLoad("GetSession", "v1"); HandShake1.PaylodType = NewPayLoad.ePaylodType.SocketRequest; NewPayLoad RC = SendSocketPayLoad(HandShake1); if (RC.Name == "SessionID") { mGingerSocketInfo.SessionID = RC.GetGuid(); } else { throw new Exception("Error in connecting to GingerSocketServer invalid Session"); } } catch (Exception e) { Console.WriteLine("Error: " + e.Message); throw e; } }
private void MessageHandler(GingerSocketInfo gingerSocketInfo) { NewPayLoad PLRC = HandlePayLoad(gingerSocketInfo.DataAsPayload); gingerSocketInfo.Response = PLRC; }