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); }
/** * Connects to the remote device. This routine will block until the connection * completes. */ public void Connect() { if (connected) { throw new IOException("Already connected"); } /* Write the CONNECT packet */ Send(AdbProtocol.GenerateConnect()); /* Start the connection thread to respond to the peer */ connectAttempted = true; this.connectionThread = new Thread(Run) { IsBackground = true }; this.connectionThread.Start(); /* Wait for the connection to go live */ lock (this) { if (!connected) { Monitor.Wait(this); } if (!connected) { throw new IOException("Connection failed"); } } }
/** * Opens an AdbStream object corresponding to the specified destination. * This routine will block until the connection completes. * @param destination The destination to open on the target * @return AdbStream object corresponding to the specified destination */ private T Open <T>(String destination) where T : AdbSessionBase { uint localId = ++lastLocalId; if (!connectAttempted) { throw new IOException("connect() must be called first"); } /* Wait for the connect response */ lock (this) { if (!connected) { Monitor.Wait(this); } if (!connected) { throw new IOException("Connection failed"); } } /* Add this stream to this list of half-open streams */ T stream = Activator.CreateInstance(typeof(T), this, localId) as T; openStreams.Add(localId, stream); /* Send the open */ Send(AdbProtocol.GenerateOpen(localId, destination)); /* Wait for the connection thread to receive the OKAY */ lock (stream) { Monitor.Wait(stream); } /* Check if the open was rejected */ if (stream.IsClosed) { throw new IOException("Stream open actively rejected by remote peer"); } /* We're fully setup now */ return(stream); }
/** * 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(); }
public void Reboot() { Send(AdbProtocol.GenerateOpen(++lastLocalId, "reboot:")); Close(); }
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; } }