public void HandleMessage(byte[] message, object target, DatasetSource ds)
        {
            BigEndianBinaryReader reader = new BigEndianBinaryReader(message);
            // read in the current time
            CarTimestamp time = new CarTimestamp(reader.ReadUInt16(), reader.ReadInt32());
            // read the feedback type
            byte feedbackType = reader.ReadByte();

            // read the length
            ushort len = reader.ReadUInt16();

            // dispatch if we can
            FeedbackType type;
            if (types.TryGetValue((int)feedbackType, out type)) {
                object[] vals = type.MapMessage(target, ds, time, reader);

                if (logWriter != null) {
                    logWriter.Write(time);
                    logWriter.Write(",");
                    logWriter.Write(feedbackType);
                    logWriter.Write(",");

                    for (int i = 0; i < vals.Length - 1; i++) {
                        logWriter.Write(vals[i]);
                        logWriter.Write(",");
                    }

                    logWriter.WriteLine(vals[vals.Length - 1]);
                }
            }
        }
        public object[] MapMessage(object target, DatasetSource ds, CarTimestamp ts, BigEndianBinaryReader reader)
        {
            // reader will be positioned at start of payload
            int nextra = 0;
            if (methodHasTimestamp)
                nextra++;
            if (methodHasMsgType)
                nextra++;

            object[] vals = new object[fields.Count];
            object[] param = null;
            if (method != null) {
                if (methodIsObjectArray) {
                    param = new object[1+nextra];
                }
                else {
                    param = new object[fields.Count + nextra];
                }

                if (methodHasTimestamp) {
                    param[0] = ts;
                    if (methodHasMsgType)
                        param[1] = id;
                }
                else if (methodHasMsgType) {
                    param[0] = id;
                }
            }

            for (int i = 0; i < fields.Count; i++) {
                object val = fields[i].MapField(reader, ds, ts);
                if (param != null && !methodIsObjectArray)
                    param[i + nextra] = val;

                vals[i] = val;
            }

            if (methodIsObjectArray && param != null) {
                param[nextra] = vals;
            }

            if (method != null) {
                method.Invoke(target, param);
            }

            return vals;
        }
        private void ListenerProc()
        {
            while (true) {
                IPEndPoint ep = new IPEndPoint(IPAddress.Any, 0);
                byte[] data = client.Receive(ref ep);

                // get the current time
                DateTime now = HighResDateTime.Now;

                if (data.Length == 5) {
                    // parse the data
                    BigEndianBinaryReader reader = new BigEndianBinaryReader(data);
                    // check that the first byte is a 0
                    if (reader.ReadByte() == 0) {
                        // read the seconds
                        ushort secs = reader.ReadUInt16();
                        // read the ticks
                        ushort ticks = reader.ReadUInt16();

                        // get the car timestamp
                        CarTimestamp ct = new CarTimestamp(secs, ticks);

                        // get the elapsed seconds since start
                        TimeSpan elapsed = now-start;
                        double localElapsedSecs = elapsed.TotalSeconds;

                        // update the diff
                        double curDiff = ct.ts-localElapsedSecs;
                        double newDiff;
                        // check if we haven't initialized the offset or the offset deviates from the just-measured offset by more than a second
                        if (double.IsNaN(offset) || Math.Abs(offset-curDiff) >= 1) {
                            newDiff = curDiff;
                        }
                        else {
                            // smooth out the offset values using an exponential filter
                            newDiff = curDiff*alpha + offset*(1-alpha);
                        }

                        // swap in the new value
                        // probably don't need an interlocked operation for this, but using it so that
                        //	we swap the entire double at once and don't get any weird problems
                        Interlocked.Exchange(ref offset, newDiff);
                    }
                }
            }
        }
        public object MapField(BigEndianBinaryReader reader, DatasetSource ds, CarTimestamp ct)
        {
            object val = MapData(ReadData(reader));

            if (!string.IsNullOrEmpty(dsitem) && ds != null) {
                IDataItemSource di;
                if (!ds.TryGetValue(dsitem, out di)) {
                    Type digType = typeof(DataItemSource<>);
                    Type diType = digType.MakeGenericType(outtype);
                    DataItemDescriptor desc = new DataItemDescriptor(dsitem, outtype, null, null, 250);
                    di = (IDataItemSource)Activator.CreateInstance(diType, desc);
                    ds.Add(dsitem, di);
                }
                di.Add(val, ct);
            }

            return val;
        }
 protected int ReadData(BigEndianBinaryReader reader)
 {
     switch (intype) {
         case InType.U8:
             return reader.ReadByte();
         case InType.S8:
             return reader.ReadSByte();
         case InType.U16:
             return reader.ReadUInt16();
         case InType.S16:
             return reader.ReadInt16();
         case InType.U32:
             return (int)reader.ReadUInt32();
         case InType.S32:
             return reader.ReadInt32();
         default:
             throw new InvalidOperationException();
     }
 }
        private void OnReceive(IAsyncResult ar)
        {
            UdpClient udp = (UdpClient)ar.AsyncState;
            try {
                IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 0);
                byte[] data = udp.EndReceive(ar, ref endpoint);

                // check if we have any pending operations
                PendingOp op = null;
                lock (pendingOps) {
                    pendingOps.TryGetValue(endpoint.Address, out op);
                    pendingOps[endpoint.Address] = null;
                }

                if (op != null && !op.cancelled) {
                    // figure out what this message is
                    if (op.messageCode == MicroMessageCodes.GetTimestamp && data.Length == 8) {
                        // we have a value message, parse
                        BigEndianBinaryReader reader = new BigEndianBinaryReader(data);
                        reader.ReadUInt16();
                        ushort secs = reader.ReadUInt16();
                        int ticks = reader.ReadInt32();
                        RaiseTimestampEvent(endpoint.Address, new MicroTimestamp(secs, ticks), true);
                    }
                    else if (op.messageCode == MicroMessageCodes.TimingMode && data.Length == 3) {
                        bool server = data[2] == 1;
                        RaiseBoolEvent(endpoint.Address, server, true, ModeReceived);
                    }
                    else if (op.messageCode == MicroMessageCodes.TimingPulse && data.Length == 3) {
                        bool result = data[2] == 1;
                        RaiseBoolEvent(endpoint.Address, result, true, PulseReceived);
                    }
                    else if (op.messageCode == MicroMessageCodes.TimingResync && data.Length == 3) {
                        bool result = data[2] == 0;
                        RaiseBoolEvent(endpoint.Address, result, true, ResyncAcknowledged);
                    }
                    else if (op.messageCode == MicroMessageCodes.TimingSync && data.Length == 3) {
                        bool result = data[2] == 1;
                        RaiseBoolEvent(endpoint.Address, result, true, SyncReceived);
                    }
                }

                udp.BeginReceive(OnReceive, udp);
            }
            catch (ObjectDisposedException) {
            }
        }