/// <summary> /// Start responding, it should be called in separate Thread. /// </summary> private void respondingParallel() { lock (responseLock) { if (responseThread != null) { responseThread.Join(); } responseThread = Thread.CurrentThread; } responder = null; try { responder = new UdpClient(Constants.UDPPort); while (true) { if (stopRequested) { return; } lock (responseLock) if (!responding) { allreadyResponding = false; responseThread = null; responder.Close(); break; } var searcherEp = new IPEndPoint(IPAddress.Any, 0); byte[] receivedBytes = null; try { receivedBytes = responder.Receive(ref searcherEp); if (receivedBytes == null || receivedBytes.Length == 0) { return; } } catch (SocketException) { continue; } if (receivedBytes == null) { continue; } var clientRequest = Encoding.UTF8.GetString(receivedBytes); if (clientRequest == "Send AppInfo") { var responseData = Encoding.UTF8.GetBytes("name=" + synch.Name + ",id=" + synch.InstanceID + ",groupid=" + synch.GroupID); responder.Send(responseData, responseData.Length, searcherEp); } else if (clientRequest == "ConnectToMe") { synch.ConnectSenderTo(searcherEp.Address); } } } catch (SocketException) { synch.CallbackError(Synchronization.ErrorType.AllreadyBindUDPPort); allreadyResponding = false; responding = false; responseThread = null; return; } finally { if (responder != null) { lock (responder) responder.Close(); } } }
/// <summary> /// Conect to given ip adress and send changes. It should be called in separate Thread. /// </summary> /// <param name="ipObject">IP adress, where to connect.</param> private void connectForSynchronizeParallel(object ipObject) { //Init IPAddress ip = (IPAddress)ipObject; NetworkStream stream = null; try { //Connect And set streams. senderClient = new TcpClient(); senderClient.Connect(ip, Constants.TCPPort); stream = senderClient.GetStream(); using (StreamReader sReader = new StreamReader(stream)) using (StreamWriter sWriter = new StreamWriter(stream)) { string line = sReader.ReadLine(); if (line == null || line[line.Length - 1] != '?') { synch.CallbackError(Synchronization.ErrorType.ConnectionProblem); return; } string[] synchParams = line.Split(';'); if (synchParams[2] == synch.InstanceID) { sWriter.WriteLine("TerminateConnection;?"); sWriter.WriteLine("EndOfConnection;?"); if (stopRequested) { return; } sWriter.Flush(); return; } else { sWriter.WriteLine("Continue;?"); if (stopRequested) { return; } sWriter.Flush(); } SendAllChanges(sWriter, DateTime.Parse(synchParams[1])); SynchronizationDevice device; lock (db) device = db.GetSynchronizationDeviceInfo(synchParams[2]); if (device != null && device.Allow) { sWriter.WriteLine("SendChanges;?"); if (stopRequested) { return; } sWriter.Flush(); receiveAndExecuteNewChanges(sReader); } else { sWriter.WriteLine("DoNotSend;?"); } sWriter.WriteLine("NowItIs;" + DateTime.Now.ToString(Constants.DateTimeFormat) + ";?"); sWriter.WriteLine("EndOfConnection;?"); if (stopRequested) { return; } sWriter.Flush(); if (!waitUntillConnectionEnd(sReader)) { return; } if (device != null && device.Allow) { device.LastSynchDate = DateTime.Now.AddSeconds(5); lock (db) db.UpdateSynchronizationDevice(device); } } } catch (SocketException) { //Connection closed } catch (IOException) { //Closed Streame due to closing of synch Form } catch (ObjectDisposedException) { //Closed Streame due to closing of synch Form } catch (NullReferenceException) { //Closed Streame due to closing connection } finally { lock (stateChangeLock) { if (senderClient != null) { lock (senderClient) { if (!closed) { closed = true; if (senderClient.Connected && senderClient.GetStream() != null) //TODO:Add connected check { senderClient.GetStream().Close(); } senderClient.Close(); } } } senderClient = null; } } }
/// <summary> /// Receiving changes and response. It should be called in separate Thread. /// </summary> /// <param name="sinceObject">Date after which changes are received.</param> private void receivingParallel(object sinceObject) { DateTime since = (DateTime)sinceObject; lock (stateChangeLock) { listener = null; receiverStream = null; receiver = null; } try { listener = new TcpListener(IPAddress.Any, Constants.TCPPort); listener.Start(); if (!waitUntillConnectionOrEnd(listener)) { return; } receiver = listener.AcceptTcpClient(); receiverStream = receiver.GetStream(); using (StreamReader cReader = new StreamReader(receiverStream)) using (StreamWriter cWriter = new StreamWriter(receiverStream)) { cWriter.WriteLine("SendMeYourChanges;" + since.ToString(Constants.DateTimeFormat) + ";" + synch.InstanceID + ";?"); if (stopRequested) { return; } cWriter.Flush(); string remoteResponse = cReader.ReadLine(); if (remoteResponse == "TerminateConnection;?") { synch.CallbackError(Synchronization.ErrorType.ConnectionLost); return; } if (!tryReceiveMaxCountChanges(cReader)) { return; } if (!receiveAllChanges(cReader)) { return; } synch.RemoteChangeFull = true; lock (sendNewChangesRequest) { if (!bypassWaiting) { Monitor.Wait(sendNewChangesRequest); } } if (!decideAndExecuteNewChanges(cReader, cWriter)) { return; } cWriter.WriteLine("EndOfConnection;?"); if (stopRequested) { return; } cWriter.Flush(); if (!waitUntillConnectionEnd(cReader)) { return; } synch.StopSynchronizing(); } } catch (SocketException) { //Closed Connection due to closing of synch Form synch.CallbackError(Synchronization.ErrorType.ConnectionLost); } catch (IOException) { //Closed Streame due to closing of synch Form synch.CallbackError(Synchronization.ErrorType.ConnectionLost); } catch (ObjectDisposedException) { //Closed object due to closing of synch Form synch.CallbackError(Synchronization.ErrorType.ConnectionLost); } catch (InvalidOperationException) { //Closed object due to closing of synch Form synch.CallbackError(Synchronization.ErrorType.ConnectionLost); } finally { lock (stateChangeLock) { if (receiver != null) { if (!closed) { closed = true; if (receiver.Connected && receiver.GetStream() != null) { receiver.GetStream().Close(); } receiver.Close(); } } receiver = null; receiverStream = null; } if (listener != null) { listener.Stop(); } } }