/// <summary> /// Parses response early recieved by AdsFinder /// </summary> /// <param name="rr"></param> /// <returns>True - if route added, False - otherwise</returns> public static bool ParseResponse(ResponseResult rr) { if (rr == null) return false; if (!rr.Buffer.Take(4).ToArray().SequenceEqual(Segment.HEADER)) return false; if (!rr.Buffer.Skip(4).Take(Segment.END.Length).ToArray().SequenceEqual(Segment.END)) return false; if (!rr.Buffer.Skip(8).Take(Segment.RESPONSE_DISCOVER.Length).ToArray().SequenceEqual(Segment.RESPONSE_ADDROUTE)) return false; rr.Shift = Segment.HEADER.Length + Segment.END.Length + Segment.RESPONSE_ADDROUTE.Length + Segment.AMSNETID.Length + Segment.PORT.Length + Segment.END.Length + Segment.END.Length; byte[] ack = rr.NextChunk(Segment.L_ROUTEACK); return (ack[0] == 0) && (ack[1] == 0); }
public async Task<ResponseResult> ReceiveAsync() { ResponseResult result = null; var worker = client.ReceiveAsync(); var task = await Task.WhenAny(worker, Task.Delay(Timeout)); if (task == worker) { UdpReceiveResult udpResult = await worker; result = new ResponseResult(udpResult); } else { client.Close(); } return result; }
public static DeviceInfo ParseResponse(ResponseResult rr) { DeviceInfo device = new DeviceInfo(); device.Address = rr.RemoteHost; if (!rr.Buffer.Take(4).ToArray().SequenceEqual(Segment.HEADER)) return device; if (!rr.Buffer.Skip(4).Take(Segment.END.Length).ToArray().SequenceEqual(Segment.END)) return device; if (!rr.Buffer.Skip(8).Take(Segment.RESPONSE_DISCOVER.Length).ToArray().SequenceEqual(Segment.RESPONSE_DISCOVER)) return device; rr.Shift = Segment.HEADER.Length + Segment.END.Length + Segment.RESPONSE_DISCOVER.Length; // AmsNetId // then skip 2 bytes of PORT + 4 bytes of ROUTE_TYPE byte[] amsNetId = rr.NextChunk(Segment.AMSNETID.Length, add: Segment.PORT.Length + Segment.ROUTETYPE_STATIC.Length); device.AmsNetId = new AdsNetId(amsNetId); // PLC NameLength byte[] bNameLen = rr.NextChunk(Segment.L_NAMELENGTH); int nameLen = bNameLen[0] == 5 && bNameLen[1] == 0 ? bNameLen[2] + bNameLen[3] * 256 : 0; byte[] bName = rr.NextChunk(nameLen - 1, add: 1); device.Name = System.Text.ASCIIEncoding.Default.GetString(bName); // TCat type byte[] tcatType = rr.NextChunk(Segment.TCATTYPE_RUNTIME.Length); if (tcatType[0] == Segment.TCATTYPE_RUNTIME[0]) { if(tcatType[2] == Segment.TCATTYPE_RUNTIME[2]) device.IsRuntime = true; } // OS version byte[] osVer = rr.NextChunk(Segment.L_OSVERSION); ushort osKey = (ushort)(osVer[0] * 256 + osVer[4]); device.OsVersion = OS_IDS.ContainsKey(osKey) ? OS_IDS[osKey] : osKey.ToString("X2"); //??? device.OS += " build " + (osVer[8] + osVer[9] * 256).ToString(); bool isUnicode = false; // looking for packet with tcat version; // usually it is in the end of the packet byte[] tail = rr.NextChunk(rr.Buffer.Length - rr.Shift, true); string tcatV = ""; int ci = tail.Length - 4; for (int i = ci; i > 0; i -= 4) { if (tail[i + 0] == 3 && tail[i + 2] == 4) { isUnicode = tail[i + 4] > 2; // Tc3 uses unicode tcatV = string.Format("{0}.{1} build {2}", tail[i + 4].ToString(), tail[i + 5].ToString(), (tail[i + 6] + tail[i + 7] * 256).ToString()); break; } } device.TcVersion = tcatV; // Comment byte[] descMarker = rr.NextChunk(Segment.L_DESCRIPTIONMARKER); int len = 0; int c = rr.Buffer.Length; if (descMarker[0] == 2) { if (isUnicode) { for (int i = 0; i < c; i += 2) { if (rr.Buffer[rr.Shift + i] == 0 && rr.Buffer[rr.Shift + i + 1] == 0) break; len += 2; } } else { for (int i = 0; i < c; i++) { if (rr.Buffer[rr.Shift + i] == 0) break; len++; } } if (len > 0) { byte[] description = rr.NextChunk(len); if (isUnicode) { byte[] asciiBytes = Encoding.Convert(Encoding.Unicode, Encoding.ASCII, description); char[] asciiChars = new char[Encoding.ASCII.GetCharCount(asciiBytes, 0, asciiBytes.Length)]; Encoding.ASCII.GetChars(asciiBytes, 0, asciiBytes.Length, asciiChars, 0); device.Comment = new string(asciiChars); } else device.Comment = ASCIIEncoding.Default.GetString(description); } } return device; }