Пример #1
0
        /// <summary>
        /// receive pack header
        /// </summary>
        /// <param name="input">input stream</param>
        /// <param name="expectCmd">expect response command</param>
        /// <param name="expectBodyLen">expect response package body length</param>
        /// <returns>errno and pkg body length</returns>
        public static RecvHeaderInfo RecvHeader(Stream input, byte expectCmd, long expectBodyLen)
        {
            byte[] header;
            int    bytes;
            long   pkgLen;

            header = new byte[FdfsProtoPkgLenSize + 2];
            if ((bytes = input.Read(header, 0, header.Length)) != header.Length)
            {
                throw new IOException("recv package size " + bytes + " != " + header.Length);
            }
            if (header[ProtoHeaderCmdIndex] != expectCmd)
            {
                throw new IOException("recv cmd: " + header[ProtoHeaderCmdIndex] + " is not correct, expect cmd: " + expectCmd);
            }
            if (header[ProtoHeaderStatusIndex] != 0)
            {
                return(new RecvHeaderInfo(header[ProtoHeaderStatusIndex], 0));
            }
            //pkg_len = BitConverter.ToInt64(header, 0);
            pkgLen = ProtoCommon.Buff2Long(header, 0);
            if (pkgLen < 0)
            {
                throw new IOException("recv body length: " + pkgLen + " < 0!");
            }
            if (expectBodyLen >= 0 && pkgLen != expectBodyLen)
            {
                throw new IOException("recv body length: " + pkgLen + " is not correct, expect length: " + expectBodyLen);
            }
            return(new RecvHeaderInfo((byte)0, pkgLen));
        }
Пример #2
0
        /**
         * delete a storage server from the tracker server
         *
         * @param trackerServer the connected tracker server
         * @param groupName     the group name of storage server
         * @param storageIpAddr the storage server ip address
         * @return true for success, false for fail
         */
        private bool deleteStorage(TrackerServer trackerServer,
                                   String groupName, String storageIpAddr)
        {
            byte[]
            header;
            byte[]
            bGroupName;
            byte[]
                   bs;
            int    len;
            Socket trackerSocket;

            trackerSocket = trackerServer.getSocket();
            using (var outputStream = new NetworkStream(trackerSocket))
            {
                bs         = _encoding.GetBytes(groupName);
                bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN];

                if (bs.Length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN)
                {
                    len = bs.Length;
                }
                else
                {
                    len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
                }

                bGroupName.Fill <byte>(0);
                Array.Copy(bs, 0, bGroupName, 0, len);

                int    ipAddrLen;
                byte[] bIpAddr = _encoding.GetBytes(storageIpAddr);
                if (bIpAddr.Length < ProtoCommon.FDFS_IPADDR_SIZE)
                {
                    ipAddrLen = bIpAddr.Length;
                }
                else
                {
                    ipAddrLen = ProtoCommon.FDFS_IPADDR_SIZE - 1;
                }

                header = ProtoCommon.packHeader(ProtoCommon.TRACKER_PROTO_CMD_SERVER_DELETE_STORAGE,
                                                ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + ipAddrLen, (byte)0);
                byte[] wholePkg = new byte[header.Length + bGroupName.Length + ipAddrLen];
                Array.Copy(header, 0, wholePkg, 0, header.Length);
                Array.Copy(bGroupName, 0, wholePkg, header.Length, bGroupName.Length);
                Array.Copy(bIpAddr, 0, wholePkg, header.Length + bGroupName.Length, ipAddrLen);
                outputStream.Write(wholePkg, 0, wholePkg.Length);

                ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(outputStream,
                                                                              ProtoCommon.TRACKER_PROTO_CMD_RESP, 0);
                this.errno = pkgInfo.errno;
                return(pkgInfo.errno == 0);
            }
        }
Пример #3
0
 public void close()
 {
     if (this.sock != null)
     {
         try
         {
             ProtoCommon.closeSocket(this.sock);
         }
         finally
         {
             this.sock = null;
         }
     }
 }
Пример #4
0
 /// <summary>
 /// pack header by FastDFS transfer protocol
 /// </summary>
 /// <param name="cmd">which command to send</param>
 /// <param name="pkgLen">package body length</param>
 /// <param name="errno">status code, should be (byte)0</param>
 /// <returns>packed byte buffer</returns>
 public static byte[] PackHeader(byte cmd, long pkgLen, byte errno)
 {
     byte[] header;
     byte[] hexLen;
     header = new byte[FdfsProtoPkgLenSize + 2];
     for (int i = 0; i < header.Length; i++)
     {
         header[i] = (byte)0;
     }
     //hex_len = BitConverter.GetBytes(pkg_len);
     hexLen = ProtoCommon.Long2Buff(pkgLen);
     Array.Copy(hexLen, 0, header, 0, hexLen.Length);
     header[ProtoHeaderCmdIndex]    = cmd;
     header[ProtoHeaderStatusIndex] = errno;
     return(header);
 }
Пример #5
0
        /**
         * receive pack header
         *
         * @param in              input stream
         * @param expect_cmd      expect response command
         * @param expect_body_len expect response package body length
         * @return RecvHeaderInfo: errno and pkg body length
         */
        public static RecvHeaderInfo recvHeader(Stream inputStream, byte expect_cmd, long expect_body_len)
        {
            byte[] header;
            int    bytes;
            long   pkg_len;

            header = new byte[FDFS_PROTO_PKG_LEN_SIZE + 2];

            if ((bytes = inputStream.Read(header, 0, header.Length)) != header.Length)
            {
                throw new IOException("recv package size " + bytes + " != " + header.Length);
            }

            if (header[PROTO_HEADER_CMD_INDEX] != expect_cmd)
            {
                throw new IOException("recv cmd: " + header[PROTO_HEADER_CMD_INDEX] + " is not correct, expect cmd: " +
                                      expect_cmd);
            }

            if (header[PROTO_HEADER_STATUS_INDEX] != 0)
            {
                return(new RecvHeaderInfo(header[PROTO_HEADER_STATUS_INDEX], 0));
            }

            pkg_len = ProtoCommon.buff2long(header, 0);
            if (pkg_len < 0)
            {
                throw new IOException("recv body length: " + pkg_len + " < 0!");
            }

            if (expect_body_len >= 0 && pkg_len != expect_body_len)
            {
                throw new IOException("recv body length: " + pkg_len + " is not correct, expect length: " +
                                      expect_body_len);
            }

            return(new RecvHeaderInfo(0, pkg_len));
        }
Пример #6
0
 protected DateTime dateValue(byte[] bs, int offset, FieldInfo filedInfo)
 {
     return(DateTimeOffset.FromUnixTimeMilliseconds(
                ProtoCommon.buff2long(bs, offset + filedInfo.offset) * 1000).DateTime);
 }
Пример #7
0
 protected int int32Value(byte[] bs, int offset, FieldInfo filedInfo)
 {
     return(ProtoCommon.buff2int(bs, offset + filedInfo.offset));
 }
Пример #8
0
 protected int intValue(byte[] bs, int offset, FieldInfo filedInfo)
 {
     return((int)ProtoCommon.buff2long(bs, offset + filedInfo.offset));
 }
Пример #9
0
        /**
         * query storage server to upload file
         *
         * @param trackerServer the tracker server
         * @param groupName     the group name to upload file to, can be empty
         * @return storage server object, return null if fail
         */
        public StorageServer getStoreStorage(TrackerServer trackerServer, String groupName)
        {
            byte[] header;
            String ip_addr;
            int    port;
            byte   cmd;
            int    out_len;
            bool   bNewConnection;
            byte   store_path;
            Socket trackerSocket;

            if (trackerServer == null)
            {
                trackerServer = getConnection();
                if (trackerServer == null)
                {
                    return(null);
                }

                bNewConnection = true;
            }
            else
            {
                bNewConnection = false;
            }

            trackerSocket = trackerServer.getSocket();
            var outputStream = new NetworkStream(trackerSocket);

            try
            {
                if (groupName == null || groupName.Length == 0)
                {
                    cmd     = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ONE;
                    out_len = 0;
                }
                else
                {
                    cmd     = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ONE;
                    out_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
                }

                header = ProtoCommon.packHeader(cmd, out_len, (byte)0);
                outputStream.Write(header, 0, header.Length);
                var encoder = Encoding.GetEncoding(ClientGlobal.g_charset);
                if (groupName != null && groupName.Length > 0)
                {
                    byte[] bGroupName;
                    byte[] bs;
                    int    group_len;

                    bs         = encoder.GetBytes(groupName);
                    bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN];

                    if (bs.Length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN)
                    {
                        group_len = bs.Length;
                    }
                    else
                    {
                        group_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
                    }

                    bGroupName.Fill <byte>(0);
                    Array.Copy(bs, 0, bGroupName, 0, group_len);
                    outputStream.Write(bGroupName, 0, bGroupName.Length);
                }

                ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(outputStream,
                                                                              ProtoCommon.TRACKER_PROTO_CMD_RESP,
                                                                              ProtoCommon.TRACKER_QUERY_STORAGE_STORE_BODY_LEN);
                this.errno = pkgInfo.errno;
                if (pkgInfo.errno != 0)
                {
                    return(null);
                }

                ip_addr = Encoding.ASCII.GetString(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN,
                                                   ProtoCommon.FDFS_IPADDR_SIZE - 1).Trim('\0');

                port = (int)ProtoCommon.buff2long(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN
                                                  + ProtoCommon.FDFS_IPADDR_SIZE - 1);
                store_path = pkgInfo.body[ProtoCommon.TRACKER_QUERY_STORAGE_STORE_BODY_LEN - 1];

                return(new StorageServer(ip_addr, port, store_path));
            }
            catch (IOException ex)
            {
                if (!bNewConnection)
                {
                    try
                    {
                        trackerServer.close();
                    }
                    catch (IOException ex1)
                    {
                    }
                }

                throw ex;
            }
            finally
            {
                outputStream.Close();
                if (bNewConnection)
                {
                    try
                    {
                        trackerServer.close();
                    }
                    catch (IOException ex1)
                    {
                    }
                }
            }
        }
Пример #10
0
        /**
         * query storage server stat info of the group
         *
         * @param trackerServer the tracker server
         * @param groupName     the group name of storage server
         * @param storageIpAddr the storage server ip address, can be null or empty
         * @return storage server stat array, return null if fail
         */
        public StructStorageStat[] listStorages(TrackerServer trackerServer,
                                                String groupName, String storageIpAddr)
        {
            byte[]
            header;
            byte[]
            bGroupName;
            byte[]
                   bs;
            int    len;
            bool   bNewConnection;
            Socket trackerSocket;

            if (trackerServer == null)
            {
                trackerServer = getConnection();
                if (trackerServer == null)
                {
                    return(null);
                }

                bNewConnection = true;
            }
            else
            {
                bNewConnection = false;
            }

            trackerSocket = trackerServer.getSocket();
            var outputStream = new NetworkStream(trackerSocket);

            try
            {
                bs         = _encoding.GetBytes(groupName);
                bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN];

                if (bs.Length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN)
                {
                    len = bs.Length;
                }
                else
                {
                    len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
                }

                bGroupName.Fill <byte>(0);
                Array.Copy(bs, 0, bGroupName, 0, len);

                int    ipAddrLen;
                byte[] bIpAddr;
                if (storageIpAddr != null && storageIpAddr.Length > 0)
                {
                    bIpAddr = _encoding.GetBytes(storageIpAddr);
                    if (bIpAddr.Length < ProtoCommon.FDFS_IPADDR_SIZE)
                    {
                        ipAddrLen = bIpAddr.Length;
                    }
                    else
                    {
                        ipAddrLen = ProtoCommon.FDFS_IPADDR_SIZE - 1;
                    }
                }
                else
                {
                    bIpAddr   = null;
                    ipAddrLen = 0;
                }

                header = ProtoCommon.packHeader(ProtoCommon.TRACKER_PROTO_CMD_SERVER_LIST_STORAGE,
                                                ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + ipAddrLen, (byte)0);
                byte[] wholePkg = new byte[header.Length + bGroupName.Length + ipAddrLen];
                Array.Copy(header, 0, wholePkg, 0, header.Length);
                Array.Copy(bGroupName, 0, wholePkg, header.Length, bGroupName.Length);
                if (ipAddrLen > 0)
                {
                    Array.Copy(bIpAddr, 0, wholePkg, header.Length + bGroupName.Length, ipAddrLen);
                }

                outputStream.Write(wholePkg, 0, wholePkg.Length);

                ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(outputStream,
                                                                              ProtoCommon.TRACKER_PROTO_CMD_RESP, -1);
                this.errno = pkgInfo.errno;
                if (pkgInfo.errno != 0)
                {
                    return(null);
                }

                ProtoStructDecoder <StructStorageStat> decoder = new ProtoStructDecoder <StructStorageStat>();
                return(decoder.decode <StructStorageStat>(pkgInfo.body, StructStorageStat.getFieldsTotalSize()));
            }
            catch (IOException ex)
            {
                if (!bNewConnection)
                {
                    try
                    {
                        trackerServer.close();
                    }
                    catch (IOException ex1)
                    {
                    }
                }

                throw ex;
            }
            catch (Exception ex)
            {
                this.errno = ProtoCommon.ERR_NO_EINVAL;
                return(null);
            }
            finally
            {
                outputStream.Close();
                if (bNewConnection)
                {
                    try
                    {
                        trackerServer.close();
                    }
                    catch (IOException ex1)
                    {
                    }
                }
            }
        }
Пример #11
0
        /**
         * list groups
         *
         * @param trackerServer the tracker server
         * @return group stat array, return null if fail
         */
        public StructGroupStat[] listGroups(TrackerServer trackerServer)
        {
            byte[] header;
            String ip_addr;
            int    port;
            byte   cmd;
            int    out_len;
            bool   bNewConnection;
            byte   store_path;
            Socket trackerSocket;

            if (trackerServer == null)
            {
                trackerServer = getConnection();
                if (trackerServer == null)
                {
                    return(null);
                }

                bNewConnection = true;
            }
            else
            {
                bNewConnection = false;
            }

            trackerSocket = trackerServer.getSocket();
            var outputStream = new NetworkStream(trackerSocket);

            try
            {
                header = ProtoCommon.packHeader(ProtoCommon.TRACKER_PROTO_CMD_SERVER_LIST_GROUP, 0, (byte)0);
                outputStream.Write(header, 0, header.Length);

                ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(outputStream,
                                                                              ProtoCommon.TRACKER_PROTO_CMD_RESP, -1);
                this.errno = pkgInfo.errno;
                if (pkgInfo.errno != 0)
                {
                    return(null);
                }

                ProtoStructDecoder <StructGroupStat> decoder = new ProtoStructDecoder <StructGroupStat>();
                return(decoder.decode <StructGroupStat>(pkgInfo.body, StructGroupStat.getFieldsTotalSize()));
            }
            catch (IOException ex)
            {
                if (!bNewConnection)
                {
                    try
                    {
                        trackerServer.close();
                    }
                    catch (IOException ex1)
                    {
                    }
                }

                throw ex;
            }
            catch (Exception ex)
            {
                this.errno = ProtoCommon.ERR_NO_EINVAL;
                return(null);
            }
            finally
            {
                outputStream.Close();
                if (bNewConnection)
                {
                    try
                    {
                        trackerServer.close();
                    }
                    catch (IOException ex1)
                    {
                    }
                }
            }
        }
Пример #12
0
        /**
         * query storage server to download file
         *
         * @param trackerServer the tracker server
         * @param cmd           command code, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ONE or
         *                      ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_UPDATE
         * @param groupName     the group name of storage server
         * @param filename      filename on storage server
         * @return storage server Socket object, return null if fail
         */
        protected ServerInfo[] getStorages(TrackerServer trackerServer,
                                           byte cmd, String groupName, String filename)
        {
            byte[] header;
            byte[] bFileName;
            byte[] bGroupName;
            byte[] bs;
            int    len;
            String ip_addr;
            int    port;
            bool   bNewConnection;
            Socket trackerSocket;

            if (trackerServer == null)
            {
                trackerServer = getConnection();
                if (trackerServer == null)
                {
                    return(null);
                }

                bNewConnection = true;
            }
            else
            {
                bNewConnection = false;
            }

            trackerSocket = trackerServer.getSocket();
            var outputStream = new NetworkStream(trackerSocket);

            try
            {
                bs         = _encoding.GetBytes(groupName);
                bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN];
                bFileName  = _encoding.GetBytes(filename);

                if (bs.Length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN)
                {
                    len = bs.Length;
                }
                else
                {
                    len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
                }

                bGroupName.Fill <byte>(0);
                Array.Copy(bs, 0, bGroupName, 0, len);

                header = ProtoCommon.packHeader(cmd, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + bFileName.Length, 0);
                byte[] wholePkg = new byte[header.Length + bGroupName.Length + bFileName.Length];
                Array.Copy(header, 0, wholePkg, 0, header.Length);
                Array.Copy(bGroupName, 0, wholePkg, header.Length, bGroupName.Length);
                Array.Copy(bFileName, 0, wholePkg, header.Length + bGroupName.Length, bFileName.Length);
                outputStream.Write(wholePkg, 0, wholePkg.Length);

                ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(outputStream,
                                                                              ProtoCommon.TRACKER_PROTO_CMD_RESP, -1);
                this.errno = pkgInfo.errno;
                if (pkgInfo.errno != 0)
                {
                    return(null);
                }

                if (pkgInfo.body.Length < ProtoCommon.TRACKER_QUERY_STORAGE_FETCH_BODY_LEN)
                {
                    throw new IOException("Invalid body Length: " + pkgInfo.body.Length);
                }

                if ((pkgInfo.body.Length - ProtoCommon.TRACKER_QUERY_STORAGE_FETCH_BODY_LEN) %
                    (ProtoCommon.FDFS_IPADDR_SIZE - 1) != 0)
                {
                    throw new IOException("Invalid body Length: " + pkgInfo.body.Length);
                }

                int server_count = 1 + (pkgInfo.body.Length - ProtoCommon.TRACKER_QUERY_STORAGE_FETCH_BODY_LEN) /
                                   (ProtoCommon.FDFS_IPADDR_SIZE - 1);

                ip_addr = Encoding.ASCII.GetString(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN,
                                                   ProtoCommon.FDFS_IPADDR_SIZE - 1).Trim('\0');
                int offset = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + ProtoCommon.FDFS_IPADDR_SIZE - 1;

                port    = (int)ProtoCommon.buff2long(pkgInfo.body, offset);
                offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE;

                ServerInfo[] servers = new ServerInfo[server_count];
                servers[0] = new ServerInfo(ip_addr, port);
                for (int i = 1; i < server_count; i++)
                {
                    servers[i] = new ServerInfo(Encoding.ASCII.GetString(
                                                    pkgInfo.body, offset, ProtoCommon.FDFS_IPADDR_SIZE - 1).Trim('\0'),
                                                port);
                    offset += ProtoCommon.FDFS_IPADDR_SIZE - 1;
                }

                return(servers);
            }
            catch (IOException ex)
            {
                if (!bNewConnection)
                {
                    try
                    {
                        trackerServer.close();
                    }
                    catch (IOException ex1)
                    {
                    }
                }

                throw ex;
            }
            finally
            {
                outputStream.Close();
                if (bNewConnection)
                {
                    try
                    {
                        trackerServer.close();
                    }
                    catch (IOException ex1)
                    {
                    }
                }
            }
        }
Пример #13
0
        /**
         * query storage servers to upload file
         *
         * @param trackerServer the tracker server
         * @param groupName     the group name to upload file to, can be empty
         * @return storage servers, return null if fail
         */
        public StorageServer[] getStoreStorages(TrackerServer trackerServer, String groupName)
        {
            byte[] header;
            String ip_addr;
            int    port;
            byte   cmd;
            int    out_len;
            bool   bNewConnection;
            Socket trackerSocket;

            if (trackerServer == null)
            {
                trackerServer = getConnection();
                if (trackerServer == null)
                {
                    return(null);
                }

                bNewConnection = true;
            }
            else
            {
                bNewConnection = false;
            }

            trackerSocket = trackerServer.getSocket();
            var outputStream = new NetworkStream(trackerSocket);

            try
            {
                if (groupName == null || groupName.Length == 0)
                {
                    cmd     = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ALL;
                    out_len = 0;
                }
                else
                {
                    cmd     = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ALL;
                    out_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
                }

                header = ProtoCommon.packHeader(cmd, out_len, (byte)0);
                outputStream.Write(header, 0, header.Length);
                var encoder = Encoding.GetEncoding(ClientGlobal.g_charset);
                if (groupName != null && groupName.Length > 0)
                {
                    byte[] bGroupName;
                    byte[] bs;
                    int    group_len;

                    bs         = encoder.GetBytes(groupName);
                    bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN];

                    if (bs.Length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN)
                    {
                        group_len = bs.Length;
                    }
                    else
                    {
                        group_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;
                    }

                    bGroupName.Fill <byte>(0);
                    Array.Copy(bs, 0, bGroupName, 0, group_len);
                    outputStream.Write(bGroupName, 0, bGroupName.Length);
                }


                ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(outputStream,
                                                                              ProtoCommon.TRACKER_PROTO_CMD_RESP, -1);
                this.errno = pkgInfo.errno;
                if (pkgInfo.errno != 0)
                {
                    return(null);
                }

                if (pkgInfo.body.Length < ProtoCommon.TRACKER_QUERY_STORAGE_STORE_BODY_LEN)
                {
                    this.errno = ProtoCommon.ERR_NO_EINVAL;
                    return(null);
                }

                int ipPortLen    = pkgInfo.body.Length - (ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + 1);
                int recordLength = ProtoCommon.FDFS_IPADDR_SIZE - 1 + ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE;

                if (ipPortLen % recordLength != 0)
                {
                    this.errno = ProtoCommon.ERR_NO_EINVAL;
                    return(null);
                }

                int serverCount = ipPortLen / recordLength;
                if (serverCount > 16)
                {
                    this.errno = ProtoCommon.ERR_NO_ENOSPC;
                    return(null);
                }

                StorageServer[] results    = new StorageServer[serverCount];
                byte            store_path = pkgInfo.body[pkgInfo.body.Length - 1];
                int             offset     = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN;

                for (int i = 0; i < serverCount; i++)
                {
                    ip_addr = Encoding.ASCII.GetString(pkgInfo.body, offset, ProtoCommon.FDFS_IPADDR_SIZE - 1).Trim(
                        '\0');
                    offset += ProtoCommon.FDFS_IPADDR_SIZE - 1;

                    port    = (int)ProtoCommon.buff2long(pkgInfo.body, offset);
                    offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE;

                    results[i] = new StorageServer(ip_addr, port, store_path);
                }

                return(results);
            }
            catch (IOException ex)
            {
                if (!bNewConnection)
                {
                    try
                    {
                        trackerServer.close();
                    }
                    catch (IOException ex1)
                    {
                    }
                }

                throw ex;
            }
            finally
            {
                outputStream.Close();
                if (bNewConnection)
                {
                    try
                    {
                        trackerServer.close();
                    }
                    catch (IOException ex1)
                    {
                    }
                }
            }
        }