I'm very new to C# (and C in general for that matter) I'm getting a byte value returned from an external source that represents the states of 8 input pins on the port of an IO device so I get a value of 0-255 representing the binary pattern present on the port.
How can I strip out the individual bits and set them as bool vars, so doing something like this:
if (inputBuffer[1] == 1)
{
IO.Input0 = true;
IO.Input1 = false;
IO.Input2 = false;
IO.Input3 = false;
IO.Input4 = false;
IO.Input5 = false;
IO.Input6 = false;
IO.Input7 = false;
}
I'm probably overexplaining what I'm trying to achieve but thought this gives the best example although highly impractical, how can I better achieve this to set the variables based on a byte value of 0-255.
Use a bitwise-and (&). Assuming Input0 represents the least significant bit:
IO.Input0 = (inputBuffer & 0x01) == 0x01;
IO.Input1 = (inputBuffer & 0x02) == 0x02;
IO.Input2 = (inputBuffer & 0x04) == 0x04;
IO.Input3 = (inputBuffer & 0x08) == 0x08;
IO.Input4 = (inputBuffer & 0x10) == 0x10;
IO.Input5 = (inputBuffer & 0x20) == 0x20;
IO.Input6 = (inputBuffer & 0x40) == 0x40;
IO.Input7 = (inputBuffer & 0x80) == 0x80;
You can also implement an extension method like the following:
public static bool IsBitSet(this byte b, int bit)
{
if(bit < 0 || bit > 7)
throw new ArgumentOutOfRangeException("bit must be between 0 and 7");
byte bitToCheck = (byte)(0x01 << bit);
return (b & bitToCheck) == bitToCheck;
}
Which you could then call like:
IO.Input4 = inputBuffer.IsBitSet(4);
Use a bitmask and the &-operator to figure this out
byte b = 100;
if(b&1 == 1) { } //bit 1 is set
if(b&2 == 2) { } //bit 2 is set
if(b&4 == 4) { } //bit 3 is set
...
I think a self written class can help. Class could contain the 8 bits and the constructor takes a byte. In the constructor you can calculate the single bits.
public class myByte
{
bool Input0 = false;
bool Input1 = false;
bool Input2 = false;
bool Input3 = false;
bool Input4 = false;
bool Input5 = false;
bool Input6 = false;
bool Input7 = false;
public myByte(byte b)
{
//written by Ic.
Input0 = b & 0x01 == 0x01;
Input1 = b & 0x02 == 0x02;
Input2 = b & 0x04 == 0x04;
Input3 = b & 0x08 == 0x08;
Input4 = b & 0x10 == 0x10;
Input5 = b & 0x20 == 0x20;
Input6 = b & 0x40 == 0x40;
Input7 = b & 0x80 == 0x80;
}
... //getter setter ...
}
You can do this.
int x= inputBuffer[1];
bit1 = ((x>>7)&1==1);
bit2 = ((x>>6)&1==1);
bit3 = ((x>>5)&1==1);
bit4 = ((x>>4)&1==1);
bit5 = ((x>>3)&1==1);
bit6 = ((x>>2)&1==1);
bit7 = ((x>>1)&1==1);
bit8 = (x&1==1);
To get 1st bit from say 11101110 value you need to right shift first bt 7 times and then doing AND operation with 1 will tell you whether the value is 1 or 0 and same solution applies for other bits as well.
You can use the BitArray class.
var bitArray = new BitArray(inputBuffer);
IO.Input1 = bitArray[byteIndex * 8 + 1];
Or
var bitArray = new BitArray(new byte[] { inputBuffer[1] });
IO.Input1 = bitArray[1];
You can also iterate it as a collection of Boolean values, and perform bitwise operation on the entire collection.
It's obviously not as performant as the other options offered here (cost of allocation) but it does provide a very neat API for bit calculations.
If the data is given to you in a Byte form and that each bit has been masked, then I would leave it as it is. Converting them to another type is unnecessary, it will be an extra work for no benefit. To get the correct bit, just use the bit mask pattern
private bool GetMaskedBit(var inputBuffer , int mask)
{
return ((inputBuffer & mask) != 0);
}
This way you parse the buffer and the required bit you wanted, this will return whether the bit has been set or not.
Related
I've a NFC reader along with MIFARE Classic 1K card. I've a Visual C# winforms project. Right now I'm able to connect to the reader and detect the card and get it's UUID. The problem I'm facing is while writing and reading data. I searched a lot on internet, found some solution even tested the demo code provided with the SDK... nothing's working.
Let me describe the workflow and code I'm using for writing, authenticating a block, sending APDU and reading the block.
Following is the code for writing data to block 5.
String tmpStr = Text;
int indx;
if (authenticateBlock(Block))
{
ClearBuffers();
SendBuff[0] = 0xFF; // CLA
SendBuff[1] = 0xD6; // INS
SendBuff[2] = 0x00; // P1
SendBuff[3] = (byte)int.Parse(Block); // P2 : Starting Block No.
SendBuff[4] = (byte)int.Parse("16"); // P3 : Data length
SendBuff[5] = 0xFF;
SendBuff[6] = 0xFF;
SendBuff[7] = 0xFF;
SendBuff[8] = 0xFF;
SendBuff[9] = 0xFF;
SendBuff[10] = 0xFF;
for (indx = 0; indx <= (tmpStr).Length - 1; indx++)
{
SendBuff[indx + 5] = (byte)tmpStr[indx];
}
SendLen = SendBuff[4] + 5;
RecvLen = 0x02;
retCode = SendAPDUandDisplay(2);
if (retCode != Card.SCARD_S_SUCCESS)
{
MessageBox.Show("fail write");
}
else
{
MessageBox.Show("write success");
}
}
else
{
MessageBox.Show("FailAuthentication");
}
CloseCardConnection();
The function SendAPDUandDisplay is as below
private int SendAPDUandDisplay(int reqType)
{
int indx;
string tmpStr = "";
pioSendRequest.dwProtocol = Aprotocol;
pioSendRequest.cbPciLength = 8;
//Display Apdu In
for (indx = 0; indx <= SendLen - 1; indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", SendBuff[indx]);
}
retCode = Card.SCardTransmit(hCard, ref pioSendRequest, ref SendBuff[0],
SendLen, ref pioSendRequest, ref RecvBuff[0], ref RecvLen);
if (retCode != Card.SCARD_S_SUCCESS)
{
return retCode;
}
else
{
try
{
tmpStr = "";
switch (reqType)
{
case 0:
for (indx = (RecvLen - 2); indx <= (RecvLen - 1); indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", RecvBuff[indx]);
}
if ((tmpStr).Trim() != "90 00")
{
//MessageBox.Show("Return bytes are not acceptable.");
return -202;
}
break;
case 1:
for (indx = (RecvLen - 2); indx <= (RecvLen - 1); indx++)
{
tmpStr = tmpStr + string.Format("{0:X2}", RecvBuff[indx]);
}
if (tmpStr.Trim() != "90 00")
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", RecvBuff[indx]);
}
else
{
tmpStr = "ATR : ";
for (indx = 0; indx <= (RecvLen - 3); indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", RecvBuff[indx]);
}
}
break;
case 2:
for (indx = 0; indx <= (RecvLen - 1); indx++)
{
tmpStr = tmpStr + " " + string.Format("{0:X2}", RecvBuff[indx]);
}
break;
}
}
catch (IndexOutOfRangeException)
{
return -200;
}
}
return retCode;
}
Function authenticateBlock is as following
private bool authenticateBlock(String block)
{
ClearBuffers();
/*SendBuff[0] = 0xFF; // CLA
SendBuff[2] = 0x00; // P1: same for all source types
SendBuff[1] = 0x82; // INS: for stored key input
SendBuff[3] = 0x00; // P2 : Memory location; P2: for stored key input
SendBuff[4] = 0x05; // P3: for stored key input
SendBuff[5] = 0x01; // Byte 1: version number
SendBuff[6] = 0x00; // Byte 2
SendBuff[7] = (byte)int.Parse(block); // Byte 3: sectore no. for stored key input
SendBuff[8] = 0x60; // Byte 4 : Key A for stored key input
SendBuff[9] = (byte)int.Parse("1"); // Byte 5 : Session key for non-volatile memory
*/
SendBuff[0] = 0xD4;
SendBuff[1] = 0x4A;
SendBuff[2] = 0x01;
SendBuff[3] = 0x00;
SendBuff[4] = (byte) int.Parse(block);
SendBuff[5] = 0xFF;
SendBuff[6] = 0xFF;
SendBuff[7] = 0xFF;
SendBuff[8] = 0xFF;
SendBuff[9] = 0xFF;
SendBuff[10] = 0xFF;
/*SendLen = 0x0A;
RecvLen = 0x02;*/
SendLen = 4;
RecvLen = 255;
retCode = SendAPDUandDisplay(2);
if (retCode != Card.SCARD_S_SUCCESS)
{
//MessageBox.Show("FAIL Authentication!");
return false;
}
return true;
}
One strange thing to notice here is that whatever values I set in sendBuff this function always returns true value and the write data code "The very first code block" returns write success message
But after executing the write data code when I read that very block "5" in my case, there is nothing present there. My read block code returns an empty string and when I try to double check if data was written and my faulty code couldn't read I use an external software to verify that was the value added or not, that software also does not show the data that I wrote and got that write success message.
Ok following is the code I'm using to read block 5.
public string readBlock(String Block)
{
string tmpStr = "";
int indx;
if (authenticateBlock(Block))
{
ClearBuffers();
/*
SendBuff[0] = 0xFF; // CLA
SendBuff[1] = 0xB0;// INS
SendBuff[2] = 0x00;// P1
SendBuff[3] = (byte)int.Parse(Block);// P2 : Block No.
SendBuff[4] = (byte)int.Parse("16");// Le
*/
SendBuff[0] = 0xD4;
SendBuff[1] = 0x40;
SendBuff[2] = 0x01;
SendBuff[3] = 0x30;
SendBuff[4] = byte.Parse(Block.ToString(), System.Globalization.NumberStyles.HexNumber);
SendBuff[5] = 0xFF;
SendBuff[6] = 0xFF;
SendBuff[7] = 0xFF;
SendBuff[8] = 0xFF;
SendBuff[9] = 0xFF;
SendBuff[10] = 0xFF;
//SendLen = 5;
//RecvLen = SendBuff[4] + 2;
SendLen = 5;
RecvLen = 255;
retCode = SendAPDUandDisplay(2);
if (retCode == -200)
{
return "outofrangeexception";
}
if (retCode == -202)
{
return "BytesNotAcceptable";
}
if (retCode != Card.SCARD_S_SUCCESS)
{
return "FailRead";
}
// Display data in text format
for (indx = 0; indx <= RecvLen - 1; indx++)
{
tmpStr = tmpStr + Convert.ToChar(RecvBuff[indx]);
}
return (tmpStr);
}
else
{
return "FailAuthentication";
}
}
Please Note that the read block method is called after checking that is a reader connected connected, if so then I call the
readblock method and it returns an empty string
I've tried several values as you would see in comments but nothing seems to help, it's been 3 long days and I'm still stuck here.
Can someone please help me figure where I'm doing it wrong and what values should I send in order to authenticate the block?
Please do me a favour that if anyone gets to knows the problem in my code or want to correctify the values I'm setting in sendBuff[] then please quote them in C# code so I can use exactly the solution you want me to implement
Any sincere help would be highly regarded, thanks in advance.
I have only experimented with mifare 1k, using Arduino.
In this instance, after detecting the card, and retrieving the UUID, It needs to select the card before reading/writing. Are you doing this select card step?
As its a S50 1K Classic the 'bytemap' is different and the process cycle while ostensibly the same you need to check that its a S50 before continuing by getting the ATR/ATS and parsing it to retrieve the switch setting. With contact its ATR, contactless ATS but is technically the same thing. Under PCSC this is asking for the readerchangestate when asking the reader is a card present, done before sending an APDU. You can also get other settings at the same time.
For MFS50 you need to perform a 'S'elect then a 'L'ogin using the sector key then read that sectors first three of 4 blocks but ignore most of the first sector block - the keys are in the fourth block along with other control bytes. The 'UID' is returned on 'S'elect, success or fail on 'L'ogin, data or 'E'rror on reading the blocks in the sector. For 14443 sector 0 the first block is occupied by the 'manufacturing' data which depends on the construct can have 4, 7 or 12 bytes as the UID with from a data point of view embedded CRC and check bytes, so cannot be used as a UID - it is a data map. Lights, C, ultralights, EV1's have a different 'bytemap' and may or may not have 'L'ogins at card or sector. These are 14443 types, there is also a 15693 type which has just data in the sectors. Some Chinese 14443 have writable manufacturing blocks, but usually its a mix of static, settings and OTP (once bit set cannot unset, used for authentication and NFC verification of size!).
Classic 1K: ident UID: 66908648, requires sector key log in (A read, B
read/write)
Sector 0:
6690864838880400468f76594d100612
00000000000000000000000000000000
00000000000000000000000000000000
ffffffffffffff078069ffffffffffff
...
Sector 15:
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
ffffffffffffff0780bcffffffffffff
Mifare ultralight: UID 0489d802a44080, might require sector login but key held elsewhere.
Sector 0:
0489D8DD
02A44080
66480900
00010001
.
Sector 1:
00000000
00000000
00000000
000000EE
15693: UID D89A1F24500104E0
Sector 0:
50555955
Sector 1:
48485353
Sector 2:
59435300
Sector 3:
00000000
...
Sector 15:
00000000
So, get the ATR/ATS and work out what card you have, then deal with it accordingly. Oh, and use the belt, braces and a piece of string approach - after writing to a card read it again to compare the written to what is expected. 15693 require sector complete writes else nothing gets written in that sector.
Will that be Type 2 NFC/NDEF - there are other standards. Have cannibalized a Zebra printer to encode and print NTAG201's bullseyes on the fly.
I am trying to figure out how to increment a starting ip address, and increment it by an offset that I specify. I have attempted to do this, but I am doing something wrong because I am getting IPs that are all over the place, not even in the same network range.
What I am currently doing is taking my starting ip and ending ip, getting the total amount of addresses then incrementing the total ips by an offset then attempting to actually increment the IP.
I am incrementing to the total ips by an offset so I know how many to increment the ip. (I am completing different tasks per offset.) Whatever the loop has incremented "t" to that is how many I increment IPs. Now that I have given the rundown, my issue only seems to be with actually incrementing ips, can anyone help me out in this situation. Thanks.
string from = txtStart.Text, to = txtEnd.Text;
uint current = from.ToUInt(), last = to.ToUInt();
ulong total = last - current;
int offset = 3; //This is an example number, it actually could be anything.
while (current <= last)
{
for (int t = 0; t < total; t += offset)
{
uint ut = Convert.ToUInt32(t);
current = current + ut;
var ip = current.ToIPAddress();
}
}
Here is the extension class I am using. They work fine.
public static class Extensions
{
public static uint ToUInt(this string ipAddress)
{
var ip = IPAddress.Parse(ipAddress);
var bytes = ip.GetAddressBytes();
Array.Reverse(bytes);
return BitConverter.ToUInt32(bytes, 0);
}
public static string ToString(this uint ipInt)
{
return ToIPAddress(ipInt).ToString();
}
public static IPAddress ToIPAddress(this uint ipInt)
{
var bytes = BitConverter.GetBytes(ipInt);
Array.Reverse(bytes);
return new IPAddress(bytes);
}
}
[TestFixture]
public class GetNextIpAddressTest
{
[Test]
public void ShouldGetNextIp()
{
Assert.AreEqual("0.0.0.1", GetNextIpAddress("0.0.0.0", 1));
Assert.AreEqual("0.0.1.0", GetNextIpAddress("0.0.0.255", 1));
Assert.AreEqual("0.0.0.11", GetNextIpAddress("0.0.0.1", 10));
Assert.AreEqual("123.14.1.101", GetNextIpAddress("123.14.1.100", 1));
Assert.AreEqual("0.0.0.0", GetNextIpAddress("255.255.255.255", 1));
}
private static string GetNextIpAddress(string ipAddress, uint increment)
{
byte[] addressBytes = IPAddress.Parse(ipAddress).GetAddressBytes().Reverse().ToArray();
uint ipAsUint = BitConverter.ToUInt32(addressBytes, 0);
var nextAddress = BitConverter.GetBytes(ipAsUint + increment);
return String.Join(".", nextAddress.Reverse());
}
}
An IPv4 address is basically a 32 bit Integer. Therefore you can just parse the substrings from e.g. 192.168.0.1 and convert each byte to an integer number:
uint byte1 = Converter.ToUint32("192");
and so on ..
Then you could just "OR" or "ADD" them together like this:
uint IP = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
and increment that integer with step_size as needed. Here is an example:
using System.IO;
using System;
class Program
{
static void Main()
{
String ipString = "192.168.0.1";
String[] ipBytes = ipString.Split('.');
uint byte1 = Convert.ToUInt32(ipBytes[0]);
uint byte2 = Convert.ToUInt32(ipBytes[1]);
uint byte3 = Convert.ToUInt32(ipBytes[2]);
uint byte4 = Convert.ToUInt32(ipBytes[3]);
uint IP = (byte1 << 24)
| (byte2 << 16)
| (byte3 << 8)
| byte4 ;
uint step_size = 90000000;
while( IP != 0xFFFFFFFF ) {
Console.WriteLine(
((IP >> 24) & 0xFF) + "." +
((IP >> 16) & 0xFF) + "." +
((IP >> 8 ) & 0xFF) + "." +
( IP & 0xFF)
);
// if (0xFFFFFFFF - IP) < step_size then we can't
// add step_size to IP due to integer overlow
// which means that we have generated all IPs and
// there isn't any left that equals IP + step_size
if( (0xFFFFFFFF - IP) < step_size ) {
break;
}
IP += step_size; // next ip address
}
}
}
Output
192.168.0.1
198.5.74.129
203.98.149.1
208.191.223.129
214.29.42.1
219.122.116.129
224.215.191.1
230.53.9.129
235.146.84.1
240.239.158.129
246.76.233.1
251.170.51.129
The following is a class I use for working with IP addresses which includes the ability to increment an IP address as well as to build a range of IPs.
public sealed class IPAddressTools
{
public static UInt32 ConvertIPv4AddressToUInt32(IPAddress address)
{
if (address == null) throw new ArgumentNullException("address", "The value of address is a null reference.");
if (address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) throw new ArgumentException("The specified address's family is invalid.", "address");
Byte[] addressBytes = address.GetAddressBytes();
UInt32 addressInteger = (((UInt32)addressBytes[0]) << 24) + (((UInt32)addressBytes[1]) << 16) + (((UInt32)addressBytes[2]) << 8) + ((UInt32)addressBytes[3]);
return addressInteger;
}
public static IPAddress ConvertUInt32ToIPv4Address(UInt32 addressInteger)
{
if (addressInteger < 0 || addressInteger > 4294967295) throw new ArgumentOutOfRangeException("addressInteger", "The value of addressInteger must be between 0 and 4294967295.");
Byte[] addressBytes = new Byte[4];
addressBytes[0] = (Byte)((addressInteger >> 24) & 0xFF);
addressBytes[1] = (Byte)((addressInteger >> 16) & 0xFF);
addressBytes[2] = (Byte)((addressInteger >> 8) & 0xFF);
addressBytes[3] = (Byte)(addressInteger & 0xFF);
return new IPAddress(addressBytes);
}
public static IPAddress IncrementIPAddress(IPAddress address, int offset)
{
return ModIPAddress(address, 1);
}
public static IPAddress ModIPAddress(IPAddress address, int offset)
{
if (address == null) throw new ArgumentNullException("address", "The value of address is a null reference.");
if (address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) throw new ArgumentException("The specified address's family is invalid.");
UInt32 addressInteger = ConvertIPv4AddressToUInt32(address);
addressInteger += offset;
return ConvertUInt32ToIPv4Address(addressInteger);
}
public static IPAddress[] GetIpRange(IPAddress address, IPAddress mask)
{
if (address == null) throw new ArgumentNullException("address", "The value of address is a null reference.");
if (mask == null) throw new ArgumentNullException("mask", "The value of mask is a null reference.");
if (address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) throw new ArgumentException("The specified address's family is invalid.");
if (mask.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) throw new ArgumentException("The specified mask's family is invalid.");
byte[] addressBytes = address.GetAddressBytes();
byte[] maskBytes = mask.GetAddressBytes();
byte[] startIpBytes = new byte[addressBytes.Length];
byte[] endIpBytes = new byte[addressBytes.Length];
for (int i = 0; i < addressBytes.Length; i++)
{
startIpBytes[i] = (byte)(addressBytes[i] & maskBytes[i]);
endIpBytes[i] = (byte)(addressBytes[i] | ~maskBytes[i]);
}
IPAddress startIp = new IPAddress(startIpBytes);
IPAddress endIp = new IPAddress(endIpBytes);
List<IPAddress> addresses = new List<IPAddress>();
for (IPAddress currentIp = startIp; ConvertIPv4AddressToUInt32(currentIp) <= ConvertIPv4AddressToUInt32(endIp); currentIp = IncrementIPAddress(currentIp))
{
addresses.Add(currentIp);
}
return addresses.ToArray();
}
}
You could also implement the + and - operators for the IPAddress class, but since it wouldn't work for all uses of the class it's probably not a good idea.
public static IPAddress operator +(IPAddress address, int offset)
{
if (address == null) throw new ArgumentNullException("address", "The value of address is a null reference.");
if (address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) throw new ArgumentException("The specified address's family is invalid.", "address");
Byte[] addressBytes = address.GetAddressBytes();
UInt32 addressInteger = (((UInt32)addressBytes[0]) << 24) + (((UInt32)addressBytes[1]) << 16) + (((UInt32)addressBytes[2]) << 8) + ((UInt32)addressBytes[3]);
addressInteger += offset;
addressBytes[0] = (Byte)((addressInteger >> 24) & 0xFF);
addressBytes[1] = (Byte)((addressInteger >> 16) & 0xFF);
addressBytes[2] = (Byte)((addressInteger >> 8) & 0xFF);
addressBytes[3] = (Byte)(addressInteger & 0xFF);
return new IPAddress(addressBytes);
}
public static IPAddress operator -(IPAddress address, int offset)
{
if (address == null) throw new ArgumentNullException("address", "The value of address is a null reference.");
if (address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) throw new ArgumentException("The specified address's family is invalid.", "address");
Byte[] addressBytes = address.GetAddressBytes();
UInt32 addressInteger = (((UInt32)addressBytes[0]) << 24) + (((UInt32)addressBytes[1]) << 16) + (((UInt32)addressBytes[2]) << 8) + ((UInt32)addressBytes[3]);
addressInteger -= offset;
addressBytes[0] = (Byte)((addressInteger >> 24) & 0xFF);
addressBytes[1] = (Byte)((addressInteger >> 16) & 0xFF);
addressBytes[2] = (Byte)((addressInteger >> 8) & 0xFF);
addressBytes[3] = (Byte)(addressInteger & 0xFF);
return new IPAddress(addressBytes);
}
In your cycle you are doing some wild increments. First increment t is 0 so ip stays the same. Second increment t is 3 so 192.168.1.1 becomes 192.168.1.4(and you save it as current). Third increment t is 6 so 192.168.1.4 becomes 192.168.1.10(and saved as current) ...
I think what you are trying to achieve is somthing like this:
string from = "192.168.1.1", to = "192.168.1.255";
uint first = from.ToUInt(), last = to.ToUInt();
ulong total = last - first;
uint offset = 3; //This is an example number, it actually could be anything.
for (uint t = 0; (ulong)t < total; t += 1)
{
uint ut = Convert.ToUInt32(t);
uint c = first + t + offset;
var ip = c.ToIPAddress();
}
Ip can be decomposed as follow
integer value= (4thOctat*2^24.3rd*2^16.2nd*2^8.1st*2^0)
e.g. 64.233.187.99
64*2^24 + 233*2^16 + 187*2^8 + 99
= 1089059683
I wrote this small example for you,
//This is regular expression to check the the ip is in correct format
private readonly Regex ip = new Regex(#"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
private void Main()
{
string IpAddress = "172.22.1.1";
if (ip.IsMatch(IpAddress))
{
//increment first octat by 5
string IncrementedIp = IncrementIP(0, 100, IPAddress.Parse(IpAddress));
if (ip.IsMatch(IncrementedIp))
{
Console.WriteLine("Incremented Ip = {0}", IncrementedIp);
}
else
{
//not valid ip address}
}
}else
{
//Not Valid Ip Address
}
}
private string IncrementIP(short octat, long Offset,IPAddress adress)
{
//octat range from 0-3
if ( octat<0 ||octat > 3) return adress.ToString();
long IpLong = AdressToInt(adress.ToString());
IpLong += (long)(Offset*(Math.Pow(2,octat*8)));
return longToAddress(IpLong);
}
static long AdressToInt(string addr)
{
return (long)(uint)IPAddress.NetworkToHostOrder(
(int)IPAddress.Parse(addr).Address);
}
static string longToAddress(long address)
{
return IPAddress.Parse(address.ToString()).ToString();
}
To evaluate a little: You simply change the numeric representation of a value from one base to another, the another in this case being the 10-base, which your code, your head and your computer language use commonly. In 10-base, you can easily perform arithmetics. Once you have done that, you change the resulting number back to another base again, for example the original one.
In the case of an IP-address, the base is 256. As said earlier, an IP-address is simply a numeric value consisting 32 bits.
Bits are 2-base (toolset: 0,1)
Your calculation happens in 10-base (0,1,2,3,4,5,6,7,8,9)
Hexa is 16-base ((0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F)
An IP-address is (4 of) 256-base (0,1,2,3,4,5,6,7,8,9,[we should have another 246 unique symbols here]). As we do not have 256 unique numeric symbols (would be too many anyway), we describe these for convenience using 10-base instead, for example 253 (but 253 should really be the 254th symbol in a symbol table, like in the ASCII-table).
There are a million cases when you want to change base, or change numeric space. One example is incrementing a date. You change to the manageable days-since-20th-centurystart-space (the actual change isn't too simple, but the good result is a 10-base representation), perform the calculation (eg. increment with 7 days), and then change back to YMD-space.
The IP-address 255.255.255.255 could also be described using the 10-base integer value 4294967295.
They Answers are right... for addition to your implementation
CheckAgain:
If My.Computer.Network.Ping(CheckIPFirst) = False Then
'=====IF IP ADDRESS NOT OCCUPIED GET=========
CheckIPFirst +=1
GETIpAddress(Counter) = CheckIPFirst
Else
'======CHECK ANOTHER IP ADDRESS=============
CheckIPFirst +=1
Goto CheckAgain
End If
Through that you will not encounter a IP Address Conflict or Same IP Address.
I'm working on a dll that parses binary data I get from a Home Automation module.
But I need some advice on some code I have.
So I get a message with some bytes, and each bit indicates a certain condition in this case.
In the code I have at the moment each condition is an enum, I put the enums in an array and check if the corresponding bit is set.
private void ParseZoneConditionFlag1(int Flag1) // Flag1 = Hex represenation of byte
{
Zone_Status_ZoneConditionFlagEnum[] FlagArray = new Zone_Status_ZoneConditionFlagEnum[8];
FlagArray[0] = Zone_Status_ZoneConditionFlagEnum.Faulted;
FlagArray[1] = Zone_Status_ZoneConditionFlagEnum.Tampered;
FlagArray[2] = Zone_Status_ZoneConditionFlagEnum.Trouble;
FlagArray[3] = Zone_Status_ZoneConditionFlagEnum.Bypassed;
FlagArray[4] = Zone_Status_ZoneConditionFlagEnum.Inhibited;
FlagArray[5] = Zone_Status_ZoneConditionFlagEnum.Low_Battery;
FlagArray[6] = Zone_Status_ZoneConditionFlagEnum.Loss_Supervision;
FlagArray[7] = Zone_Status_ZoneConditionFlagEnum.Reserved;
base.CheckBitsSet(FlagArray, Flag1, ZoneConditionFlags_List);
}
private void ParseZoneConditionFlag2(int Flag2)
{
Zone_Status_ZoneConditionFlagEnum[] FlagArray = new Zone_Status_ZoneConditionFlagEnum[8];
FlagArray[0] = Zone_Status_ZoneConditionFlagEnum.Alarm_Memory;
FlagArray[1] = Zone_Status_ZoneConditionFlagEnum.Bypass_Memory;
FlagArray[2] = Zone_Status_ZoneConditionFlagEnum.Reserved;
FlagArray[3] = Zone_Status_ZoneConditionFlagEnum.Reserved;
FlagArray[4] = Zone_Status_ZoneConditionFlagEnum.Reserved;
FlagArray[5] = Zone_Status_ZoneConditionFlagEnum.Reserved;
FlagArray[6] = Zone_Status_ZoneConditionFlagEnum.Reserved;
FlagArray[7] = Zone_Status_ZoneConditionFlagEnum.Reserved;
base.CheckBitsSet(FlagArray, Flag2, ZoneConditionFlags_List);
}
And the method were I check the actual bits
protected void CheckBitsSet<T>(T[] ConstantArray, int HexValue, List<T> DestinationList)
{
byte b = (byte) HexValue;
for (int i = 0; i < Mask.Length; i++)
{
if(IsBitSet(b, i))
{
DestinationList.Add(ConstantArray[i]);
}
}
}
public bool IsBitSet(byte b, int pos)
{
return (b & (1 << pos)) != 0;
}
This works, but I wonder if there is a cleaner way to do this.
With cleaner I mean without having to add the right enums to an array each time.
How about just:
[Flags]
enum MyFlags : short
{
None = 0,
Faulted = 1 << 0,
Tampered = 1 << 1,
Trouble = 1 << 2,
Bypassed = 1 << 3,
Inhibited = 1 << 4,
LowBattery = 1 << 5,
LossOfSupervision = 1 << 6,
AlarmMemory = 1 << 8,
BypassMemory = 1 << 9
}
static bool IsSet(MyFlags value, MyFlags flag)
{
return ((value & flag) == flag);
}
and read the value as a 2-byte value (short, being careful about endianness), and then cast to MyFlags.
To check for any flag, just:
MyFlags value = ...
bool isAlarmMemory = IsSet(value, MyFlags.AlarmMemory);
It gets tricker when you talk about composite flags, i.e.
bool memoryProblem = IsSet(value, MyFlags.AlarmMemory | MyFlags.BypassMemory);
as you need to figure out whether you mean "is any of these flags set?" vs "are all of these flags set?"
It comes down to the test;
return ((value & flag) == flag); // means "are all set"
return ((value & flag) != 0); // means "is any set"
For reading:
// this is just some garbage that I'm pretending is a message from
// your module; I'm assuming the byte numbers in the image are
// zero-based, so the two that we want are: \/\/\/ (the 6,3)
byte[] data = { 12, 63, 113, 0, 13, 123, 14, 6, 3, 14, 15 };
// and I'm assuming "byte 7" and "byte 8" (image) are zero-based;
// MyFlags uses byte 7 *first*, so it is little-endian; we can get that
// via:
short flagsRaw = (short)(data[7] | (data[8] << 8));
MyFlags flags = (MyFlags)flagsRaw;
// flags has value Tampered | Trouble | AlarmMemory | BypassMemory,
// which is what we expect for {6,3}
Use this:
[Flags]
public enum MyEnum
{
Value1 = 1,
Value2 = 2,
Value3 = 4,
Value5 = 8
}
(...)
void Func(int flag)
{
MyEnum #enum = (MyEnum)flag;
// Testing, whether a flag is set
if ((#enum & MyEnum.Value1) != 0) // sth
}
I'm making a tile based 2d platformer and every byte of memory is precious. I have one byte field that can hold values from 0 to 255, but what I need is two properties with values 0~15. How can I turn one byte field into two properties like that?
do you mean just use the lower 4 bits for one value and the upper 4 bits for the other?
to get two values from 1 byte use...
a = byte & 15;
b = byte / 16;
setting is just the reverse as
byte = a | b * 16;
Using the shift operator is better but the compiler optimizers usually do this for you nowadays.
byte = a | (b << 4);
To piggy back off of sradforth's answer, and to answer your question about properties:
private byte _myByte;
public byte LowerHalf
{
get
{
return (byte)(_myByte & 15);
}
set
{
_myByte = (byte)(value | UpperHalf * 16);
}
}
public byte UpperHalf
{
get
{
return (byte)(_myByte / 16);
}
set
{
_myByte = (byte)(LowerHalf | value * 16);
}
}
Below are some properties and some backing store, I've tried to write them in a way that makes the logic easy to follow.
private byte HiAndLo = 0;
private const byte LoMask = 15; // 00001111
private const byte HiMask = 240; // 11110000
public byte Lo
{
get
{
// ----&&&&
return (byte)(this.hiAndLo & LoMask);
}
set
{
if (value > LoMask) //
{
// Values over 15 are too high.
throw new OverflowException();
}
// &&&&0000
// 0000----
// ||||||||
this.hiAndLo = (byte)((this.hiAndLo & HiMask) | value);
}
}
public byte Hi
{
get
{
// &&&&XXXX >> 0000&&&&
return (byte)((this.hiAndLo & HiMask) >> 4);
}
set
{
if (value > LoMask)
{
// Values over 15 are too high.
throw new OverflowException();
}
// -------- << ----0000
// XXXX&&&&
// ||||||||
this.hiAndLo = (byte)((hiAndLo & LoMask) | (value << 4 ));
}
}
Interestingly, I can find implementations for the Internet Checksum in almost every language except C#. Does anyone have an implementation to share?
Remember, the internet protocol specifies that:
"The checksum field is the 16 bit one's complement of the one's
complement sum of all 16 bit words in the header. For purposes of
computing the checksum, the value of the checksum field is zero."
More explanation can be found from Dr. Math.
There are some efficiency pointers available, but that's not really a large concern for me at this point.
Please include your tests! (Edit: Valid comment regarding testing someone else's code - but I am going off of the protocol and don't have test vectors of my own and would rather unit test it than put into production to see if it matches what is currently being used! ;-)
Edit: Here are some unit tests that I came up with. They test an extension method which iterates through the entire byte collection. Please comment if you find fault in the tests.
[TestMethod()]
public void InternetChecksum_SimplestValidValue_ShouldMatch()
{
IEnumerable<byte> value = new byte[1]; // should work for any-length array of zeros
ushort expected = 0xFFFF;
ushort actual = value.InternetChecksum();
Assert.AreEqual(expected, actual);
}
[TestMethod()]
public void InternetChecksum_ValidSingleByteExtreme_ShouldMatch()
{
IEnumerable<byte> value = new byte[]{0xFF};
ushort expected = 0xFF;
ushort actual = value.InternetChecksum();
Assert.AreEqual(expected, actual);
}
[TestMethod()]
public void InternetChecksum_ValidMultiByteExtrema_ShouldMatch()
{
IEnumerable<byte> value = new byte[] { 0x00, 0xFF };
ushort expected = 0xFF00;
ushort actual = value.InternetChecksum();
Assert.AreEqual(expected, actual);
}
I knew I had this one stored away somewhere...
http://cyb3rspy.wordpress.com/2008/03/27/ip-header-checksum-function-in-c/
Well, I dug up an implementation from an old code base and it passes the tests I specified in the question, so here it is (as an extension method):
public static ushort InternetChecksum(this IEnumerable<byte> value)
{
byte[] buffer = value.ToArray();
int length = buffer.Length;
int i = 0;
UInt32 sum = 0;
UInt32 data = 0;
while (length > 1)
{
data = 0;
data = (UInt32)(
((UInt32)(buffer[i]) << 8)
|
((UInt32)(buffer[i + 1]) & 0xFF)
);
sum += data;
if ((sum & 0xFFFF0000) > 0)
{
sum = sum & 0xFFFF;
sum += 1;
}
i += 2;
length -= 2;
}
if (length > 0)
{
sum += (UInt32)(buffer[i] << 8);
//sum += (UInt32)(buffer[i]);
if ((sum & 0xFFFF0000) > 0)
{
sum = sum & 0xFFFF;
sum += 1;
}
}
sum = ~sum;
sum = sum & 0xFFFF;
return (UInt16)sum;
}
I have made an implementation of the IPv4 header checksum calculation, as defined in RFC 791.
Extension Methods
public static ushort GetInternetChecksum(this ReadOnlySpan<byte> bytes)
=> CalculateChecksum(bytes, ignoreHeaderChecksum: true);
public static bool IsValidChecksum(this ReadOnlySpan<byte> bytes)
// Should equal zero (valid)
=> CalculateChecksum(bytes, ignoreHeaderChecksum: false) == 0;
The Checksum Calculation
using System.Buffers.Binary;
private static ushort CalculateChecksum(ReadOnlySpan<byte> bytes, bool ignoreHeaderChecksum)
{
ushort checksum = 0;
for (int i = 0; i <= 18; i += 2)
{
// i = 0 e.g. [0..2] Version and Internal Header Length
// i = 2 e.g. [2..4] Total Length
// i = 4 e.g. [4..6] Identification
// i = 6 e.g. [6..8] Flags and Fragmentation Offset
// i = 8 e.g. [8..10] TTL and Protocol
// i = 10 e.g. [10..12] Header Checksum
// i = 12 e.g. [12..14] Source Address #1
// i = 14 e.g. [14..16] Source Address #2
// i = 16 e.g. [16..18] Destination Address #1
// i = 18 e.g. [18..20] Destination Address #2
if (ignoreHeaderChecksum && i == 10) continue;
ushort value = BinaryPrimitives.ReadUInt16BigEndian(bytes[i..(i + 2)]);
// Each time a carry occurs, we must add a 1 to the sum
if (checksum + value > ushort.MaxValue)
{
checksum++;
}
checksum += value;
}
// One’s complement
return (ushort)~checksum;
}