protected void Write(byte[] payload, int offset, int count, bool flush) { lock (this) { /* Make sure we're ready for a write */ while (!isClosed && !writeReady) { Monitor.Wait(this); } Thread.MemoryBarrier(); writeReady = false; if (isClosed) { throw new IOException("Stream closed"); } } /* Generate a WRITE packet and send it */ AdbMessage packet = AdbProtocol.GenerateWrite(localId, remoteId, payload, offset, count); adbConn.Send(packet); if (flush) { adbConn.Flush(); } }
/** * Called by the connection thread to send an OKAY packet, allowing the * other side to continue transmission. */ internal void SendReady() { /* Generate and send a READY packet */ AdbMessage packet = AdbProtocol.GenerateReady(localId, remoteId); adbConn.Send(packet); }
/** * Read and parse an ADB message from the supplied input stream. * This message is NOT validated. * @param in InputStream object to read data from * @return An AdbMessage object represented the message read */ public static AdbMessage ReadAdbMessage(BinaryStream inStream) { AdbMessage msg = new AdbMessage(); inStream.IsLittleEndian = true; /* Pull out header fields */ msg.command = inStream.ReadUInt32(); msg.arg0 = inStream.ReadUInt32(); msg.arg1 = inStream.ReadUInt32(); uint payloadLength = inStream.ReadUInt32(); uint checksum = inStream.ReadUInt32(); uint magic = inStream.ReadUInt32(); if (msg.command != (magic ^ 0xFFFFFFFF)) { throw new IOException("message error"); } /* If there's a payload supplied, read that too */ if (payloadLength > 0) { msg.payload = new byte[payloadLength]; inStream.Fill(msg.payload); if (GetPayloadChecksum(msg.payload) != checksum) { throw new IOException("checksum error"); } } return(msg); }
/** * Closes the stream. This sends a close message to the peer. */ public void Close() { lock (this) { /* This may already be closed by the remote host */ if (isClosed) { return; } /* Notify readers/writers that we've closed */ NotifyClose(); } AdbMessage packet = AdbProtocol.GenerateClose(localId, remoteId); adbConn.Send(packet); adbConn.Flush(); }
/** * This function generates an ADB message given the fields. * @param cmd Command identifier * @param arg0 First argument * @param arg1 Second argument * @param payload Data payload * @return Byte array containing the message */ public static AdbMessage GenerateMessage(uint cmd, uint arg0, uint arg1, byte[] payload, int offset, int count) { AdbMessage message = new AdbMessage() { command = cmd, arg0 = arg0, arg1 = arg1 }; if (count > 0 && payload != null) { message.payload = new byte[count]; Array.Copy(payload, 0, message.payload, offset, count); } else { message.payload = payload; } return(message); }
internal void Send(AdbMessage packet) { packet.WriteTo(stream); }
public void Run() { while (true) { try { /* Read and parse a message off the socket's input stream */ AdbMessage msg = AdbMessage.ReadAdbMessage(stream); switch (msg.command) { /* Stream-oriented commands */ case AdbProtocol.CMD_OKAY: case AdbProtocol.CMD_WRTE: case AdbProtocol.CMD_CLSE: /* We must ignore all packets when not connected */ if (!connected) { continue; } /* Get the stream object corresponding to the packet */ AdbSessionBase waitingStream; if (!openStreams.TryGetValue(msg.arg1, out waitingStream)) { continue; } lock (waitingStream) { if (msg.command == AdbProtocol.CMD_OKAY) { /* We're ready for writes */ waitingStream.UpdateRemoteId(msg.arg0); waitingStream.ReadyForWrite(); /* Unwait an open/write */ Monitor.Pulse(waitingStream); } else if (msg.command == AdbProtocol.CMD_WRTE) { /* Got some data from our partner */ waitingStream.AddPayload(msg.payload); /* Tell it we're ready for more */ waitingStream.SendReady(); } else if (msg.command == AdbProtocol.CMD_CLSE) { /* He doesn't like us anymore :-( */ openStreams.Remove(msg.arg1); /* Notify readers and writers */ waitingStream.NotifyClose(); } } break; case AdbProtocol.CMD_AUTH: AdbMessage packet; if (msg.arg0 == AdbProtocol.AUTH_TYPE_TOKEN) { /* This is an authentication challenge */ if (sentSignature) { /* We've already tried our signature, so send our public key */ packet = AdbProtocol.GenerateAuth(AdbProtocol.AUTH_TYPE_RSA_PUBLIC, crypto.GetAdbPublicKeyPayload()); } else { /* We'll sign the token */ packet = AdbProtocol.GenerateAuth(AdbProtocol.AUTH_TYPE_SIGNATURE, crypto.SignAdbTokenPayload(msg.payload)); sentSignature = true; } /* Write the AUTH reply */ packet.WriteTo(stream); } break; case AdbProtocol.CMD_CNXN: lock (this) { /* We need to store the max data size */ maxData = (int)msg.arg1; /* Mark us as connected and unwait anyone waiting on the connection */ connected = true; //conn.notifyAll(); Monitor.PulseAll(this); } break; default: /* Unrecognized packet, just drop it */ break; } } catch (ThreadAbortException) { /* The cleanup is taken care of by a combination of this thread * and close() */ break; } catch (Exception e) { Debug.WriteLine(e); break; } } /* This thread takes care of cleaning up pending streams */ lock (this) { CleanupStreams(); Monitor.PulseAll(this); connectAttempted = false; } }