public int write_punch_hole(RemoteVolumeInfo rvi, long disk_offset, int size)
        {
            byte[] header      = new byte[128];
            byte[] header_recv = new byte[128];

            long seqn = Prepare_Header(header, RCS_OP.WRITE_PUNCH_HOLE, rvi.drive_id, disk_offset, size);

            rvi.server.Send(header);

            try
            {
                rvi.server.Receive(header_recv);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception in recv hdr for punchhole " + ex.Message);
                return(-1);
            }
            RFSCommHeader hobj = new RFSCommHeader();

            hobj.bytestream_to_headerobj(header_recv, 0);

            DEFS.ASSERT(hobj.seq_num == seqn && hobj.datasize == size, "Sequence number mismatchin write 2");

            if (hobj.optype == RCS_OP.WRITE_ACK)
            {
                return(size);
            }
            else
            {
                Console.WriteLine("write error: + " + hobj.optype);
                return(-1);
            }
        }
        public int read(RemoteVolumeInfo rvi, long disk_offset, byte[] buffer, int bufoffset, int size)
        {
            byte[] header      = new byte[128];
            byte[] header_recv = new byte[128];

            long seqn = Prepare_Header(header, RCS_OP.READ, rvi.drive_id, disk_offset, size);

            rvi.server.Send(header);

            rvi.server.Receive(header_recv);
            RFSCommHeader hobj = new RFSCommHeader();

            hobj.bytestream_to_headerobj(header_recv, 0);
            if (hobj.optype == RCS_OP.READ_REPLY)
            {
                int recv_ds = 0;
                DEFS.ASSERT(hobj.seq_num == seqn && hobj.datasize == size, "Sequence number mismatchin read");
                while (recv_ds < hobj.datasize)
                {
                    int sx = rvi.server.Receive(buffer, recv_ds, hobj.datasize - recv_ds, SocketFlags.None);
                    recv_ds += sx;
                }
                return(size);
            }
            else
            {
                Console.WriteLine("read error: + " + hobj.optype + " seq=" + hobj.seq_num + " size=" + hobj.datasize);
                return(-1);
            }
        }
        /*
         * Connect to the tcp port and establish the connection.
         * For all reads/writes, use the udp port.
         */
        public RemoteVolumeInfo connect(IPAddress ipaddr, int port, int driveid)
        {
            Console.WriteLine("in icomm connect " + ipaddr + "," + port + " driveid=" + driveid);

            try
            {
                IPEndPoint ipep   = new IPEndPoint(ipaddr, port);
                Socket     server = new Socket(AddressFamily.InterNetwork,
                                               SocketType.Stream, ProtocolType.Tcp);
                server.Connect(ipep);

                Console.WriteLine("icomm, connecting to server");

                RemoteVolumeInfo rvi = new RemoteVolumeInfo();
                rvi.server   = server;
                rvi.ipaddr   = ipaddr;
                rvi.port     = port;
                rvi.drive_id = driveid;

                byte[] header      = new byte[128];
                byte[] header_recv = new byte[128];

                long seqn = Prepare_Header(header, RCS_OP.CONNECT, rvi.drive_id, 0, 0);
                server.Send(header);
                Console.WriteLine("icomm, sent CONNECT, waiting for reply");

                server.Receive(header_recv);
                RFSCommHeader hobj = new RFSCommHeader();
                hobj.bytestream_to_headerobj(header_recv, 0);

                DEFS.ASSERT(hobj.seq_num == seqn, "Sequence number mismatch in connect");

                if (hobj.optype == RCS_OP.CONNECT_ACK_OKAY)
                {
                    Console.WriteLine("icomm, connected to server");
                    Console.WriteLine("icomm, remote says drive size = " + hobj.driveoffset);
                    rvi.drive_size = hobj.driveoffset; //overloaded value;
                    return(rvi);
                }
                else
                {
                    Console.WriteLine("icomm, connecting to server failed");
                    return(null);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("icomm, exception " + e.Message);
                return(null);
            }
        }
        private long Prepare_Header(byte[] buf, RCS_OP op, int did, long offset, int size)
        {
            long retval = seq_num++;

            switch (op)
            {
            case RCS_OP.NO_OP:
            case RCS_OP.CONNECT:
            case RCS_OP.READ:
            case RCS_OP.WRITE:
            case RCS_OP.DISCONNECT:
            case RCS_OP.WRITE_PUNCH_HOLE:
                RFSCommHeader hobj = new RFSCommHeader(op, did, offset, size);
                hobj.seq_num = retval;
                hobj.headerobj_to_bytestream(buf, 0);
                break;
                //assert otherwize
            }
            return(retval);
        }
        public int write(RemoteVolumeInfo rvi, long disk_offset, byte[] buffer, int bufoffset, int size)
        {
            byte[] header      = new byte[128];
            byte[] header_recv = new byte[128];

            long seqn = Prepare_Header(header, RCS_OP.WRITE, rvi.drive_id, disk_offset, size);

            rvi.server.Send(header);

            int send_ds = 0;

            while (send_ds < size)
            {
                int sz = rvi.server.Send(buffer, bufoffset + send_ds, size - send_ds, SocketFlags.None);
                send_ds += sz;
            }
            try
            {
                rvi.server.Receive(header_recv);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception in write " + ex.Message);
                return(-1);
            }
            RFSCommHeader hobj = new RFSCommHeader();

            hobj.bytestream_to_headerobj(header_recv, 0);

            DEFS.ASSERT(hobj.seq_num == seqn && hobj.datasize == size, "Sequence number mismatchin write");

            if (hobj.optype == RCS_OP.WRITE_ACK)
            {
                return(size);
            }
            else
            {
                Console.WriteLine("write error: + " + hobj.optype);
                return(-1);
            }
        }
 private long Prepare_Header(byte[] buf, RCS_OP op, int did, long offset, int size)
 {
     long retval = seq_num++;
     switch (op)
     {
         case RCS_OP.NO_OP:
         case RCS_OP.CONNECT:
         case RCS_OP.READ:
         case RCS_OP.WRITE:
         case RCS_OP.DISCONNECT:
         case RCS_OP.WRITE_PUNCH_HOLE:
             RFSCommHeader hobj = new RFSCommHeader(op, did, offset, size);
             hobj.seq_num = retval;
             hobj.headerobj_to_bytestream(buf, 0);
             break;
         //assert otherwize
     }
     return retval;
 }
        public int write_punch_hole(RemoteVolumeInfo rvi, long disk_offset, int size)
        {
            byte[] header = new byte[128];
            byte[] header_recv = new byte[128];

            long seqn = Prepare_Header(header, RCS_OP.WRITE_PUNCH_HOLE, rvi.drive_id, disk_offset, size);
            rvi.server.Send(header);

            try
            {
                rvi.server.Receive(header_recv);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception in recv hdr for punchhole " + ex.Message);
                return -1;
            }
            RFSCommHeader hobj = new RFSCommHeader();
            hobj.bytestream_to_headerobj(header_recv, 0);

            DEFS.ASSERT(hobj.seq_num == seqn && hobj.datasize == size, "Sequence number mismatchin write 2");

            if (hobj.optype == RCS_OP.WRITE_ACK)
            {
                return size;
            }
            else
            {
                Console.WriteLine("write error: + " + hobj.optype);
                return -1;
            }
        }
        public int write(RemoteVolumeInfo rvi, long disk_offset, byte[] buffer, int bufoffset, int size)
        {
            byte[] header = new byte[128];
            byte[] header_recv = new byte[128];

            long seqn = Prepare_Header(header, RCS_OP.WRITE, rvi.drive_id, disk_offset, size);
            rvi.server.Send(header);

            int send_ds = 0;
            while (send_ds < size)
            {
                int sz = rvi.server.Send(buffer, bufoffset + send_ds, size - send_ds, SocketFlags.None);
                send_ds += sz;
            }
            try
            {
                rvi.server.Receive(header_recv);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception in write " + ex.Message);
                return -1;
            }
            RFSCommHeader hobj = new RFSCommHeader();
            hobj.bytestream_to_headerobj(header_recv, 0);

            DEFS.ASSERT(hobj.seq_num == seqn && hobj.datasize == size, "Sequence number mismatchin write");

            if (hobj.optype == RCS_OP.WRITE_ACK)
            {
                return size;
            }
            else
            {
                Console.WriteLine("write error: + " + hobj.optype);
                return -1;
            }
        }
        public int read(RemoteVolumeInfo rvi, long disk_offset, byte[] buffer, int bufoffset, int size)
        {
            byte[] header = new byte[128];
            byte[] header_recv = new byte[128];

            long seqn = Prepare_Header(header, RCS_OP.READ, rvi.drive_id, disk_offset, size);
            rvi.server.Send(header);

            rvi.server.Receive(header_recv);
            RFSCommHeader hobj = new RFSCommHeader();
            hobj.bytestream_to_headerobj(header_recv, 0);
            if (hobj.optype == RCS_OP.READ_REPLY)
            {
                int recv_ds = 0;
                DEFS.ASSERT(hobj.seq_num == seqn && hobj.datasize == size, "Sequence number mismatchin read");
                while (recv_ds < hobj.datasize)
                {
                    int sx = rvi.server.Receive(buffer, recv_ds, hobj.datasize - recv_ds, SocketFlags.None);
                    recv_ds += sx;
                }
                return size;
            }
            else
            {
                Console.WriteLine("read error: + " + hobj.optype + " seq=" + hobj.seq_num + " size=" + hobj.datasize);
                return -1;
            }
        }
        /*
         * Connect to the tcp port and establish the connection.
         * For all reads/writes, use the udp port.
         */
        public RemoteVolumeInfo connect(IPAddress ipaddr, int port, int driveid)
        {
            Console.WriteLine("in icomm connect " + ipaddr + "," + port + " driveid=" + driveid);

            try
            {
                IPEndPoint ipep = new IPEndPoint(ipaddr, port);
                Socket server = new Socket(AddressFamily.InterNetwork,
                                  SocketType.Stream, ProtocolType.Tcp);
                server.Connect(ipep);

                Console.WriteLine("icomm, connecting to server");

                RemoteVolumeInfo rvi = new RemoteVolumeInfo();
                rvi.server = server;
                rvi.ipaddr = ipaddr;
                rvi.port = port;
                rvi.drive_id = driveid;

                byte[] header = new byte[128];
                byte[] header_recv = new byte[128];

                long seqn = Prepare_Header(header, RCS_OP.CONNECT, rvi.drive_id, 0, 0);
                server.Send(header);
                Console.WriteLine("icomm, sent CONNECT, waiting for reply");

                server.Receive(header_recv);
                RFSCommHeader hobj = new RFSCommHeader();
                hobj.bytestream_to_headerobj(header_recv, 0);

                DEFS.ASSERT(hobj.seq_num == seqn, "Sequence number mismatch in connect");

                if (hobj.optype == RCS_OP.CONNECT_ACK_OKAY)
                {
                    Console.WriteLine("icomm, connected to server");
                    Console.WriteLine("icomm, remote says drive size = " + hobj.driveoffset);
                    rvi.drive_size = hobj.driveoffset; //overloaded value;
                    return rvi;
                }
                else
                {
                    Console.WriteLine("icomm, connecting to server failed");
                    return null;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("icomm, exception " + e.Message);
                return null;
            }
        }