public void SendData(byte[] nextPacket, byte msgFamily, byte msgType)
        {
            OIMSG msg = new OIMSG(msgFamily, msgType, nextPacket);

            msg.timestamp = NOW();
            SendData(msg);
        }
        public void SendData(OIMSG msg)
        {
            if (msg.data.Length != 0)
            {
                if (OnDataOut != null)
                {
                    OnDataOut.Invoke(msg);
                }
            }

            if (connected)
            {
                if (msg.data.Length != 0)
                {
                    packageSequenceID++;
                    UInt32 partsAm     = (UInt32)((msg.data.Length + cutoffLength - 1) / cutoffLength); // Round Up The Result Of Integer Division
                    UInt32 currentPart = 1;

                    while (msg.data.Length > 0)
                    {
                        byte[] cutData = new byte[0];
                        if (msg.data.Length > cutoffLength)
                        {
                            cutData = new byte[cutoffLength];
                            Array.Copy(msg.data, cutData, cutoffLength);

                            int    remainingLen = msg.data.Length - cutoffLength;
                            byte[] remainder    = new byte[remainingLen];
                            Array.Copy(msg.data, cutoffLength, remainder, 0, remainingLen);
                            msg.data = remainder;
                        }
                        else
                        {
                            cutData  = msg.data;
                            msg.data = new byte[0];
                        }

                        byte[] sendBytes;
                        using (MemoryStream fs = new MemoryStream())
                            using (BinaryWriter writer = new BinaryWriter(fs)) {
                                writer.Write((byte)msg.msgFamily);
                                writer.Write((byte)msg.msgType);
                                writer.Write((UInt16)0);
                                writer.Write(packageSequenceID);
                                writer.Write(partsAm);
                                writer.Write(currentPart);
                                writer.Write((UInt64)msg.timestamp);
                                writer.Write(cutData);
                                sendBytes = fs.ToArray();
                            }
                        _BufferSendData(sendBytes);
                        currentPart++;
                    }
                }
            }
        }
        public OIMSG GetNewData()
        {
            OIMSG returnMsg = null;

            //byte[] returnBytes = null;
            lock (_receiveQueueLock) {
                if (_receiveQueue.Count > 0)
                {
                    //returnBytes = _receiveQueue.Dequeue();
                    returnMsg = _receiveQueue.Dequeue();
                }
            }
            //return returnBytes;
            return(returnMsg);
        }
        private void HandleReceivedData(byte[] inData)
        {
            if (debugLevel > 3)
            {
                string dString = Encoding.ASCII.GetString(inData);
                Debug.Log(dString.Length + "  " + (byte)inData[0] + "  " + dString);
            }

            byte magicByte = inData[0];

            if (magicByte == 100)
            {
                string json = Encoding.ASCII.GetString(inData, 1, inData.Length - 1);
                try {
                    AnswerObject obj = JsonUtility.FromJson <AnswerObject>(json);
                    if (obj.type == "answer")
                    {
                        if (debugLevel > 1)
                        {
                            Debug.Log("MM Answer: " + obj.address + ":" + obj.port);
                        }
                        _remoteAddress = obj.address;
                        _remotePort    = obj.port;
                        Punch();
                        Punch();
                    }
                    if (obj.type == "punch")    // received punch packet from other client -> connection works
                    {
                        lastReceivedHB = currentTime;
                        connected      = true;
                    }
                    return; // return if package was a json package
                } catch (Exception e) { Debug.Log(e.ToString()); }
            }
            else     //if (magicByte == 0x14) {
            {
                lastReceivedHB = currentTime;
                OIMSG msg = new OIMSG();

                using (MemoryStream str = new MemoryStream(inData)) {
                    using (BinaryReader reader = new BinaryReader(str)) {
                        msg.msgFamily = reader.ReadByte();
                        msg.msgType   = reader.ReadByte();
                        UInt16 unused2 = reader.ReadUInt16();
                        msg.sequenceID  = reader.ReadUInt32();
                        msg.partsAm     = reader.ReadUInt32();
                        msg.currentPart = reader.ReadUInt32();
                        msg.timestamp   = reader.ReadUInt64();
                    }
                }

                msg.data = new byte[inData.Length - headerLen];
                Array.Copy(inData, headerLen, msg.data, 0, inData.Length - headerLen);

                //if (debugLevel > 1) Debug.Log("family: "+msg.msgFamily+" type: " +msg.msgType+" packageSequenceID:  " + msg.sequenceID + ", partsAm: " + msg.partsAm + ", currentPart: " + msg.currentPart + ", size: " + inData.Length);
                if (debugLevel > 1)
                {
                    Debug.Log("family: " + msg.msgFamily + " type: " + msg.msgType + ", partsAm: " + msg.partsAm + ", currentPart: " + msg.currentPart);
                }
                if (msg.partsAm == 1)
                {
                    lock (_receiveQueueLock) {
                        _receiveQueue.Enqueue(msg);
                    }
                    if (OnDataIn != null)
                    {
                        OnDataIn.Invoke(msg);
                    }
                }
                else if (msg.partsAm > 1)
                {
                    if (!_dataParts.ContainsKey(msg.sequenceID))
                    {
                        byte[][] parts = new byte[msg.partsAm][];
                        parts[msg.currentPart - 1] = msg.data;
                        _dataParts.Add(msg.sequenceID, parts);
                    }
                    else
                    {
                        byte[][] parts = _dataParts[msg.sequenceID];
                        parts[msg.currentPart - 1] = msg.data;

                        bool dataComplete   = true;
                        int  concatDataSize = 0;
                        for (int i = 0; i < msg.partsAm; i++)
                        {
                            if (parts[i] == null)
                            {
                                dataComplete = false;
                                break;
                            }
                            concatDataSize += parts[i].Length;
                        }
                        if (dataComplete)
                        {
                            _dataParts.Remove(msg.sequenceID);
                            byte[] concatData = new byte[concatDataSize];
                            int    idx        = 0;
                            for (int i = 0; i < msg.partsAm; i++)
                            {
                                Array.Copy(parts[i], 0, concatData, idx, parts[i].Length);
                                idx += parts[i].Length;
                            }

                            msg.data = concatData;
                            lock (_receiveQueueLock)
                                _receiveQueue.Enqueue(msg);
                            if (OnDataIn != null)
                            {
                                OnDataIn.Invoke(msg);
                            }
                        }
                    }
                }
            }

            /*
             * else {
             *  lastReceivedHB = currentTime;
             *  if (OnDataIn != null) OnDataIn.Invoke(inData);
             *  lock (_receiveQueueLock)
             *      _receiveQueue.Enqueue(inData);
             * }
             */
        }