async void SendTask() { while (true) { if (sendbuf.Count > 0) { var payload = sendbuf.Dequeue(); GREHeader outhead = new GREHeader { flags_ver = 0, protocol = payload.Type }; //TODO: callback to print packet now? maybe another task? switch (payload.Type) { case 0x86dd: var v6outHeader = IPv6Header.FromBytes(payload.Data, 0); Console.WriteLine($"Type: {v6outHeader.nextHeader} Payload: {v6outHeader.payloadLen} From: {v6outHeader.source} To: {v6outHeader.dest}"); break; case 0x0800: var v4outHeader = IPv4Header.FromBytes(payload.Data, 0); Console.WriteLine($"Type: {v4outHeader.protocol} Size: {v4outHeader.totalLen} From: {v4outHeader.source} To: {v4outHeader.dest}"); break; case 0x88B5: // code for private experimentation Console.WriteLine($"FCP"); break; default: Console.WriteLine($"GRE Invalid Type: 0x{payload.Type:x4} {payload.Data.Length} bytes"); break; } var packet = new List <ArraySegment <byte> > { new ArraySegment <byte>(outhead.ToBytes()), new ArraySegment <byte>(payload.Data) }; await Task.Factory.FromAsync( (callback, state) => gresock.BeginSend(packet, SocketFlags.None, callback, state) , gresock.EndSend, null); } else { //TODO: better way to wait for new packets? await Task.Delay(1); } } }
PackedFrame packet_to_circuit(byte[] buffer, int startAt, int size) { var frame = new List <VarInt>(); frame.Add(1); // firstsignal = 1 we start at the beginning of the map... frame.Add(((size + 3) / 4) + 2); // sigcount = enough signals to hold all the bytes plus two for feathernet header... frame.Add(0); // grey = broadcast / placeholder for feathernet dest frame.Add(1); // white = 1 to mark feathernet map int i; for (i = startAt; i < startAt + size; i += 4) { Int32 nextword = ((buffer[i] << 24) | (buffer[i + 1] << 16) | (buffer[i + 2] << 8) | (buffer[i + 3])); // clear tail bytes if last word... if ((startAt + size) - i < 4) { nextword = (Int32)(nextword & (0xffffffff << ((4 - ((startAt + size) - i)) * 8))); } frame.Add(nextword); } // add a world-id to be consistent with other clusterio traffic VarInt srcid = ID; var head = IPv6Header.FromBytes(buffer, startAt); var ipdest = head.dest; VarInt dstid, featherdst; if (ipdest.IsIPv6Multicast) { dstid = 0xffffffff; featherdst = 0; } else { var ipdestbytes = ipdest.GetAddressBytes(); dstid = ((ipdestbytes[8] << 24) | (ipdestbytes[9] << 16) | (ipdestbytes[10] << 8) | (ipdestbytes[11])); featherdst = ((ipdestbytes[12] << 24) | (ipdestbytes[13] << 16) | (ipdestbytes[14] << 8) | (ipdestbytes[15])); } frame[2] = featherdst; return(new PackedFrame(dstid, srcid, frame, Feathernet_0_16)); }
void ReceivedBytes(byte[] rcvbuf) { // convert to signals and OnRecieve() switch (rcvbuf[0] >> 4) { case 4: var v4Header = IPv4Header.FromBytes(rcvbuf, 0); if (v4Header.protocol != 47) { break; // only GRE... this should be handled by socket, but just to be sure... } if (v4Header.headLen != 5) { break; // don't currently handle any options } var GRE4Header = GREHeader.FromBytes(rcvbuf, (v4Header.headLen * 4)); if (GRE4Header.flags_ver != 0) { break; // don't support any GRE flags, version is always 0 } // convert inner to json for clusterio and submit... for now we only have v6 inner switch (GRE4Header.protocol) { case 0x86dd: var v6inHeader = IPv6Header.FromBytes(rcvbuf, ((v4Header.headLen + 1) * 4)); Console.WriteLine($"Type: {v6inHeader.nextHeader} Payload: {v6inHeader.payloadLen} From: {v6inHeader.source} To: {v6inHeader.dest}"); if (v6inHeader.payloadLen + 40 <= ((Feathernet_0_16.Count - 2) * 4)) { if (v6inHeader.nextHeader == 44) { Console.WriteLine("Fragmented packet dropped"); } else { var circpacket = packet_to_circuit(rcvbuf, ((v4Header.headLen + 1) * 4), v6inHeader.totalLen).Unpack(); circpacket.origin = this; OnReceive?.Invoke(circpacket); } } else { Console.WriteLine("Too large"); } break; default: break; } break; case 6: var v6Header = IPv6Header.FromBytes(rcvbuf, 0); var GRE6Header = GREHeader.FromBytes(rcvbuf, 40); break; default: break; } }