예제 #1
0
        public SpStream Encode(SpType type, SpObject obj)
        {
            SpStream stream = new SpStream();

            if (Encode(type, obj, stream) == false)
            {
                if (stream.IsOverflow())
                {
                    if (stream.Position > MAX_SIZE)
                    {
                        return(null);
                    }

                    int size = stream.Position;
                    size   = ((size + 7) / 8) * 8;
                    stream = new SpStream(size);
                    if (Encode(type, obj, stream) == false)
                    {
                        return(null);
                    }
                }
                else
                {
                    return(null);
                }
            }

            return(stream);
        }
예제 #2
0
        public bool Request(string proto, SpObject args, int session, SpStream stream)
        {
            SpStream encode_stream = EncodeRequest(proto, args, session);

            encode_stream.Position = 0;
            return(SpPacker.Pack(encode_stream, stream));
        }
예제 #3
0
        public SpRpcResult Dispatch(SpStream stream)
        {
            SpStream unpack_stream = SpPacker.Unpack(stream);

            unpack_stream.Position = 0;
            SpObject header = mHostTypeManager.Codec.Decode(mHeaderType, unpack_stream);

            int session = 0;

            if (header["session"] != null)
            {
                session = header["session"].AsInt();
            }

            int ud = 0;

            if (header["ud"] != null)
            {
                ud = header["ud"].AsInt();
            }

            if (header["type"] != null)
            {
                // handle request
                SpProtocol protocol = mHostTypeManager.GetProtocolByTag(header["type"].AsInt());
                SpObject   obj      = mHostTypeManager.Codec.Decode(protocol.Request, unpack_stream);
                if (session != 0)
                {
                    mSessions[session] = protocol;
                }

                return(new SpRpcResult(session, protocol, SpRpcOp.Request, obj, ud));
            }
            else
            {
                // handle response
                if (mSessions.ContainsKey(session) == false)
                {
                    return(new SpRpcResult());
                }

                SpProtocol protocol = mSessions[session];
                mSessions.Remove(session);

                if (protocol == null)
                {
                    return(new SpRpcResult());
                }

                if (protocol.Response == null)
                {
                    return(new SpRpcResult(session, protocol, SpRpcOp.Response, null, ud));
                }

                SpObject obj = mAttachTypeManager.Codec.Decode(protocol.Response, unpack_stream);
                return(new SpRpcResult(session, protocol, SpRpcOp.Response, obj, ud));
            }
        }
예제 #4
0
        public static bool Unpack(SpStream input, SpStream output)
        {
            int src_size   = input.Tail;
            int src_offset = input.Offset;

            byte[] src = input.Buffer;

            while (src_offset < src_size)
            {
                byte header = src[src_offset];
                src_offset++;

                if (header == 0xff)
                {
                    if (src_offset > src_size)
                    {
                        return(false);
                    }

                    int n = (src[src_offset] + 1) * 8;
                    if (src_size - src_offset < n + 1)
                    {
                        return(false);
                    }

                    src_offset++;
                    output.Write(src, src_offset, n);
                    src_offset += n;
                }
                else
                {
                    for (int i = 0; i < 8; i++)
                    {
                        int nz = (header >> i) & 1;
                        if (nz != 0)
                        {
                            if (src_offset > src_size)
                            {
                                return(false);
                            }

                            output.Write(src[src_offset]);
                            src_offset++;
                        }
                        else
                        {
                            output.Write((byte)0);
                        }
                    }
                }
            }

            return(output.IsOverflow() == false);
        }
예제 #5
0
        public bool Encode(SpType type, SpObject obj, SpStream stream)
        {
            if (type == null || obj == null || stream == null)
            {
                return(false);
            }

            //mStream = stream;
            bool success = EncodeInternal(type, obj, stream);

            return(success && stream.IsOverflow() == false);
        }
예제 #6
0
        public static void WriteFF(byte[] src, int src_offset, SpStream output, int n, int correctPos)
        {
            int align8_n = (n + 7) & (~7);

            output.Write((byte)0xff);
            output.Write((byte)(align8_n / 8 - 1));
            output.Write(src, src_offset, n);
            for (int i = 0; i < align8_n - n; i++)
            {
                output.Write((byte)0);
            }
            output.CorrectLength(correctPos);
        }
예제 #7
0
        private static int PackSeg(byte[] src, int src_offset, SpStream output, int n)
        {
            byte header  = 0;
            int  notzero = 0;

            int dest_begin = output.Position;

            output.Position++;

            for (int i = 0; i < 8; i++)
            {
                if (src[src_offset + i] != 0)
                {
                    notzero++;
                    header |= (byte)(1 << i);

                    output.Write(src[src_offset + i]);
                }
            }

            if ((notzero == 7 || notzero == 6) && n > 0)
            {
                notzero = 8;
            }

            if (notzero == 8)
            {
                if (n > 0)
                {
                    return(8);
                }
                else
                {
                    return(10);
                }
            }

            int dest_end = output.Position;

            output.Position = dest_begin;
            output.Write(header);
            output.Position = dest_end;

            return(notzero + 1);
        }
예제 #8
0
        public static SpStream Unpack(SpStream input)
        {
            SpStream stream = new SpStream();

            int pos = input.Position;

            if (Unpack(input, stream) == false)
            {
                stream = new SpStream(stream.Position);

                input.Position = pos;
                if (Unpack(input, stream) == false)
                {
                    return(null);
                }
            }

            return(stream);
        }
예제 #9
0
        public static SpStream Pack(SpStream input)
        {
            SpStream stream = new SpStream();

            int pos = input.Position;

            if (Pack(input, stream) == false)
            {
                int size = stream.Position;
                size   = ((size + 7) / 8) * 8;
                stream = new SpStream(size);

                input.Position = pos;
                // do we need this check? it's not possible it will return false this time
                if (Pack(input, stream) == false)
                {
                    return(null);
                }
            }

            return(stream);
        }
예제 #10
0
        public SpStream Response(int session, SpObject args)
        {
            SpObject header = new SpObject();

            header.Insert("session", session);

            SpStream encode_stream = new SpStream();

            mHostTypeManager.Codec.Encode(mHeaderType, header, encode_stream);

            if (session != 0 && mSessions.ContainsKey(session))
            {
                mHostTypeManager.Codec.Encode(mSessions[session].Response, args, encode_stream);
            }

            SpStream pack_stream = new SpStream();

            encode_stream.Position = 0;
            SpPacker.Pack(encode_stream, pack_stream);

            pack_stream.Position = 0;
            return(pack_stream);
        }
예제 #11
0
        private SpStream EncodeRequest(string proto, SpObject args, int session)
        {
            if (mAttachTypeManager == null || mHostTypeManager == null || mHeaderType == null)
            {
                return(null);
            }

            SpProtocol protocol = mAttachTypeManager.GetProtocolByName(proto);

            if (protocol == null)
            {
                return(null);
            }

            SpObject header = new SpObject();

            header.Insert("type", protocol.Tag);
            if (session != 0)
            {
                header.Insert("session", session);
            }

            SpStream stream = mHostTypeManager.Codec.Encode(mHeaderType, header);

            if (stream == null)
            {
                return(null);
            }

            if (args != null)
            {
                if (mAttachTypeManager.Codec.Encode(protocol.Request, args, stream) == false)
                {
                    if (stream.IsOverflow())
                    {
                        if (stream.Position > SpCodec.MAX_SIZE)
                        {
                            return(null);
                        }

                        int size = stream.Position;
                        size   = ((size + 7) / 8) * 8;
                        stream = new SpStream(size);
                        if (mAttachTypeManager.Codec.Encode(protocol.Request, args, stream) == false)
                        {
                            return(null);
                        }
                    }
                    else
                    {
                        return(null);
                    }
                }
            }

            if (session != 0)
            {
                mSessions[session] = protocol;
            }

            return(stream);
        }
예제 #12
0
        public static bool Pack(SpStream input, SpStream output)
        {
            int src_size = input.Length;

            if (src_size % 8 != 0)
            {
                int new_size = ((src_size + 7) / 8) * 8;
                if (input.Capacity < new_size)
                {
                    SpStream new_input = new SpStream(new_size);
                    Array.Copy(input.Buffer, input.Offset, new_input.Buffer, new_input.Offset, input.Length);
                    new_input.Position = new_input.Offset;
                    input    = new_input;
                    src_size = new_size;
                }
                else
                {
                    int pos = input.Position;
                    input.Position = input.Tail;
                    for (int i = src_size; i < new_size; i++)
                    {
                        input.Write((byte)0);
                    }

                    input.Position = pos;
                }
            }

            int src_start  = input.Offset;
            int src_offset = input.Offset;

            byte[] src = input.Buffer;

            int ff_n          = 0;
            int ff_src_start  = 0;
            int ff_dest_start = 0;

            for (; src_offset < src_size; src_offset += 8)
            {
                int pos = output.Position;
                int n   = PackSeg(src, src_offset, output, ff_n);

                if (n == 10)
                {
                    ff_src_start  = src_offset;
                    ff_dest_start = pos;
                    ff_n          = 1;
                }
                else if (n == 8 && ff_n > 0)
                {
                    ff_n++;
                    if (ff_n == 256)
                    {
                        output.Position = ff_dest_start;
                        WriteFF(src, ff_src_start, output, 256 * 8, n);
                        ff_n = 0;
                    }
                }
                else
                {
                    if (ff_n > 0)
                    {
                        output.Position = ff_dest_start;
                        WriteFF(src, ff_src_start, output, ff_n * 8, n);
                        ff_n = 0;
                    }
                }

                output.Position = pos + n;
            }

            if (ff_n == 1)
            {
                output.Position = ff_dest_start;
                WriteFF(src, ff_src_start, output, 8, 0);
            }
            else if (ff_n > 1)
            {
                output.Position = ff_dest_start;
                WriteFF(src, ff_src_start, output, src_size - (ff_src_start - src_start), 0);
            }

            return(output.IsOverflow() == false);
        }
예제 #13
0
        private bool EncodeInternal(SpType type, SpObject obj, SpStream mStream)
        {
            if (mStream == null || type == null || obj == null)
            {
                return(false);
            }

            // buildin type decoding should not be here
            if (mTypeManager.IsBuildinType(type))
            {
                return(false);
            }

            int begin = mStream.Position;

            // fn. will be update later
            short fn = 0;

            mStream.Write(fn);

            List <KeyValuePair <SpObject, SpField> > objs = new List <KeyValuePair <SpObject, SpField> >();
            int current_tag = -1;

            Dictionary <int, SpField> .ValueCollection.Enumerator en = type.Fields.Values.GetEnumerator();
            while (en.MoveNext())
            {
                SpField f = en.Current;

                if (f == null)
                {
                    return(false);
                }

                SpObject o = obj[f.Name];
                if (o == null || IsTypeMatch(f, o) == false)
                {
                    continue;
                }

                if (f.Tag <= current_tag)
                {
                    return(false);
                }

                if (f.Tag - current_tag > 1)
                {
                    mStream.Write((short)(2 * (f.Tag - current_tag - 1) - 1));
                    fn++;
                }

                bool standalone = true;
                if (f.IsTable == false)
                {
                    if (f.Type == mTypeManager.Boolean)
                    {
                        int value = o.AsBoolean() ? 1 : 0;
                        mStream.Write((short)((value + 1) * 2));
                        standalone = false;
                    }
                    else if (f.Type == mTypeManager.Integer)
                    {
                        long value = o.AsLong();
                        if (value >= 0 && value < 0x7fff)
                        {
                            mStream.Write((short)((value + 1) * 2));
                            standalone = false;
                        }
                    }
                }

                if (standalone)
                {
                    objs.Add(new KeyValuePair <SpObject, SpField>(o, f));
                    mStream.Write((short)0);
                }

                fn++;
                current_tag = f.Tag;
            }

            List <KeyValuePair <SpObject, SpField> > .Enumerator e = objs.GetEnumerator();
            while (e.MoveNext())
            {
                KeyValuePair <SpObject, SpField> entry = e.Current;

                if (entry.Value.IsTable)
                {
                    int array_begin = mStream.Position;
                    int size        = 0;
                    mStream.Write(size);

                    if (entry.Value.Type == mTypeManager.Integer)
                    {
                        byte len = 4;

                        Dictionary <object, SpObject> .Enumerator enumerator = entry.Key.AsTable().GetEnumerator();
                        while (enumerator.MoveNext())
                        {
                            SpObject o = enumerator.Current.Value;
                            if (o.IsLong())
                            {
                                len = 8;
                                break;
                            }
                        }

                        mStream.Write(len);
                        enumerator = entry.Key.AsTable().GetEnumerator();
                        while (enumerator.MoveNext())
                        {
                            SpObject o = enumerator.Current.Value;
                            if (len == 4)
                            {
                                mStream.Write(o.AsInt());
                            }
                            else
                            {
                                mStream.Write(o.AsLong());
                            }
                        }
                    }
                    else if (entry.Value.Type == mTypeManager.Boolean)
                    {
                        Dictionary <object, SpObject> .Enumerator enumerator = entry.Key.AsTable().GetEnumerator();
                        while (enumerator.MoveNext())
                        {
                            SpObject o = enumerator.Current.Value;
                            mStream.Write((byte)(o.AsBoolean() ? 1 : 0));
                        }
                    }
                    else if (entry.Value.Type == mTypeManager.String)
                    {
                        Dictionary <object, SpObject> .Enumerator enumerator = entry.Key.AsTable().GetEnumerator();
                        while (enumerator.MoveNext())
                        {
                            SpObject o = enumerator.Current.Value;
                            byte[]   b = Encoding.UTF8.GetBytes(o.AsString());
                            mStream.Write(b.Length);
                            mStream.Write(b);
                        }
                    }
                    else
                    {
                        Dictionary <object, SpObject> .Enumerator enumerator = entry.Key.AsTable().GetEnumerator();
                        while (enumerator.MoveNext())
                        {
                            SpObject o = enumerator.Current.Value;

                            int obj_begin = mStream.Position;
                            int obj_size  = 0;
                            mStream.Write(obj_size);

                            if (EncodeInternal(entry.Value.Type, o, mStream) == false)
                            {
                                return(false);
                            }

                            int obj_end = mStream.Position;
                            obj_size         = (int)(obj_end - obj_begin - 4);
                            mStream.Position = obj_begin;
                            mStream.Write(obj_size);
                            mStream.Position = obj_end;
                        }
                    }

                    int array_end = mStream.Position;
                    size             = (int)(array_end - array_begin - 4);
                    mStream.Position = array_begin;
                    mStream.Write(size);
                    mStream.Position = array_end;
                }
                else
                {
                    if (entry.Key.IsString())
                    {
                        byte[] b = Encoding.UTF8.GetBytes(entry.Key.AsString());
                        mStream.Write(b.Length);
                        mStream.Write(b);
                    }
                    else if (entry.Key.IsInt())
                    {
                        mStream.Write((int)4);
                        mStream.Write(entry.Key.AsInt());
                    }
                    else if (entry.Key.IsLong())
                    {
                        mStream.Write((int)8);
                        mStream.Write(entry.Key.AsLong());
                    }
                    else if (entry.Key.IsBoolean())
                    {
                        // boolean should not be here
                        return(false);
                    }
                    else
                    {
                        int obj_begin = mStream.Position;
                        int obj_size  = 0;
                        mStream.Write(obj_size);

                        if (EncodeInternal(entry.Value.Type, entry.Key, mStream) == false)
                        {
                            return(false);
                        }

                        int obj_end = mStream.Position;
                        obj_size         = (int)(obj_end - obj_begin - 4);
                        mStream.Position = obj_begin;
                        mStream.Write(obj_size);
                        mStream.Position = obj_end;
                    }
                }
            }

            int end = mStream.Position;

            mStream.Position = begin;
            mStream.Write(fn);
            mStream.Position = end;

            return(true);
        }
예제 #14
0
 public bool Encode(string proto, SpObject obj, SpStream stream)
 {
     return(Encode(mTypeManager.GetType(proto), obj, stream));
 }
예제 #15
0
        public SpObject Decode(SpType type, SpStream mStream)
        {
            if (mStream == null || type == null)
            {
                return(null);
            }

            // buildin type decoding should not be here
            if (mTypeManager.IsBuildinType(type))
            {
                return(null);
            }

            SpObject obj = new SpObject();

            List <int> tags        = new List <int>();
            int        current_tag = 0;

            short fn = mStream.ReadInt16();

            for (short i = 0; i < fn; i++)
            {
                int value = (int)mStream.ReadUInt16();

                if (value == 0)
                {
                    tags.Add(current_tag);
                    current_tag++;
                }
                else
                {
                    if (value % 2 == 0)
                    {
                        SpField f = type.GetFieldByTag(current_tag);
                        if (f == null)
                        {
                            continue;
                        }

                        value = value / 2 - 1;
                        if (f.Type == mTypeManager.Integer)
                        {
                            obj.Insert(f.Name, value);
                        }
                        else if (f.Type == mTypeManager.Boolean)
                        {
                            obj.Insert(f.Name, (value == 0 ? false : true));
                        }
                        else
                        {
                            continue;
                        }

                        current_tag++;
                    }
                    else
                    {
                        //System.Console.WriteLine(string.Format("decode value: {0}",value));
                        current_tag += (value + 1) / 2;
                    }
                }
            }

            for (int c = 0; c < tags.Count; c++)
            {
                int tag = tags[c];

                SpField f = type.GetFieldByTag(tag);
                if (f == null)
                {
                    continue;
                }

                if (f.IsTable)
                {
                    int size = mStream.ReadInt32();
                    if (size == 0)
                    {
                        continue;            //empty table
                    }
                    if (f.Type == mTypeManager.Integer)
                    {
                        byte n     = mStream.ReadByte();
                        int  count = (size - 1) / n;

                        SpObject tbl = new SpObject();
                        for (int i = 0; i < count; i++)
                        {
                            switch (n)
                            {
                            case 4:
                                tbl.Insert(i, mStream.ReadInt32());
                                break;

                            case 8:
                                tbl.Insert(i, mStream.ReadInt64());
                                break;

                            default:
                                return(null);
                            }
                        }

                        obj.Insert(f.Name, tbl);
                    }
                    else if (f.Type == mTypeManager.Boolean)
                    {
                        SpObject tbl = new SpObject();
                        for (int i = 0; i < size; i++)
                        {
                            tbl.Insert(i, mStream.ReadBoolean());
                        }

                        obj.Insert(f.Name, tbl);
                    }
                    else if (f.Type == mTypeManager.String)
                    {
                        SpObject tbl = new SpObject();
                        int      k   = 0;
                        while (size > 0)
                        {
                            int str_len = mStream.ReadInt32();
                            size -= 4;
                            tbl.Insert(k, Encoding.UTF8.GetString(mStream.ReadBytes(str_len), 0, str_len));
                            k++;
                            size -= str_len;
                        }

                        obj.Insert(f.Name, tbl);
                    }
                    else if (f.Type == null)
                    {
                        // unknown type
                        mStream.ReadBytes(size);
                    }
                    else
                    {
                        SpObject tbl = new SpObject();
                        int      k   = 0;
                        while (size > 0)
                        {
                            int obj_len = mStream.ReadInt32();
                            size -= 4;

                            SpObject o = Decode(f.Type, mStream);
                            if (f.KeyName != null)
                            {
                                tbl.Insert(o.AsTable()[f.KeyName].Value, o);
                            }
                            else
                            {
                                tbl.Insert(k, o);
                            }

                            k++;
                            size -= obj_len;
                        }

                        obj.Insert(f.Name, tbl);
                    }
                }
                else
                {
                    int size = mStream.ReadInt32();

                    if (f.Type == mTypeManager.Integer)
                    {
                        switch (size)
                        {
                        case 4:
                            obj.Insert(f.Name, mStream.ReadInt32());
                            break;

                        case 8:
                            obj.Insert(f.Name, mStream.ReadInt64());
                            break;

                        default:
                            continue;
                        }
                    }
                    else if (f.Type == mTypeManager.Boolean)
                    {
                        // boolean should not be here
                        return(null);
                    }
                    else if (f.Type == mTypeManager.String)
                    {
                        obj.Insert(f.Name, Encoding.UTF8.GetString(mStream.ReadBytes(size), 0, size));
                    }
                    else if (f.Type == null)
                    {
                        // unknown type
                        mStream.ReadBytes(size);
                    }
                    else
                    {
                        obj.Insert(f.Name, Decode(f.Type, mStream));
                    }
                }
            }

            return(obj);
        }
예제 #16
0
 public SpObject Decode(string proto, SpStream stream)
 {
     return(Decode(mTypeManager.GetType(proto), stream));
 }