LCOV - code coverage report
Current view: directory - src/trusted/debug_stub - session.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 100 82 82.0 %
Date: 2014-07-02 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2010 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : #include <assert.h>
       8                 : #include <string.h>
       9                 : #include <stdlib.h>
      10                 : 
      11                 : #include <string>
      12                 : #include <sstream>
      13                 : 
      14                 : #include "native_client/src/shared/platform/nacl_log.h"
      15                 : #include "native_client/src/trusted/debug_stub/packet.h"
      16                 : #include "native_client/src/trusted/debug_stub/platform.h"
      17                 : #include "native_client/src/trusted/debug_stub/session.h"
      18                 : #include "native_client/src/trusted/debug_stub/transport.h"
      19                 : #include "native_client/src/trusted/debug_stub/util.h"
      20                 : 
      21                 : using port::IPlatform;
      22                 : using port::ITransport;
      23                 : 
      24                 : namespace gdb_rsp {
      25                 : 
      26              35 : Session::Session(ITransport *transport)
      27                 :   : io_(transport),
      28                 :     flags_(0),
      29                 :     seq_(0),
      30              35 :     connected_(true) {
      31              35 : }
      32                 : 
      33              19 : Session::~Session() {
      34              19 : }
      35                 : 
      36              32 : void Session::SetFlags(uint32_t flags) {
      37              32 :   flags_ |= flags;
      38              32 : }
      39                 : 
      40               2 : void Session::ClearFlags(uint32_t flags) {
      41               2 :   flags_ &= ~flags;
      42               2 : }
      43                 : 
      44            4456 : uint32_t Session::GetFlags() {
      45            4456 :   return flags_;
      46                 : }
      47                 : 
      48               1 : bool Session::IsDataAvailable() {
      49               1 :   return io_->IsDataAvailable();
      50                 : }
      51                 : 
      52           11254 : bool Session::Connected() {
      53           11254 :   return connected_;
      54                 : }
      55                 : 
      56              33 : void Session::Disconnect() {
      57              33 :   io_->Disconnect();
      58              33 :   connected_ = false;
      59              33 : }
      60                 : 
      61           16110 : bool Session::GetChar(char *ch) {
      62           16110 :   if (!io_->Read(ch, 1)) {
      63              31 :     Disconnect();
      64              31 :     return false;
      65                 :   }
      66                 : 
      67           16079 :   return true;
      68                 : }
      69                 : 
      70                 : 
      71             838 : bool Session::SendPacket(Packet *pkt) {
      72                 :   char ch;
      73                 : 
      74             823 :   do {
      75             838 :     if (!SendPacketOnly(pkt)) return false;
      76                 : 
      77                 :     // If ACKs are off, we are done.
      78             838 :     if (GetFlags() & IGNORE_ACK) break;
      79                 : 
      80                 :     // Otherwise, poll for '+'
      81             838 :     if (!GetChar(&ch)) return false;
      82                 : 
      83                 :     // Retry if we didn't get a '+'
      84                 :   } while (ch != '+');
      85                 : 
      86             823 :   return true;
      87                 : }
      88                 : 
      89                 : 
      90             905 : bool Session::SendPacketOnly(Packet *pkt) {
      91                 :   const char *ptr;
      92                 :   char ch;
      93             905 :   std::stringstream outstr;
      94                 : 
      95             905 :   char run_xsum = 0;
      96                 :   int32_t seq;
      97                 : 
      98             905 :   ptr = pkt->GetPayload();
      99             905 :   size_t size = pkt->GetPayloadSize();
     100                 : 
     101             905 :   if (!pkt->GetSequence(&seq) && (GetFlags() & USE_SEQ)) {
     102               0 :     pkt->SetSequence(seq_++);
     103                 :   }
     104                 : 
     105                 :   // Signal start of response
     106             905 :   outstr << '$';
     107                 : 
     108                 :   // If there is a sequence, send as two nibble 8bit value + ':'
     109             905 :   if (pkt->GetSequence(&seq)) {
     110               0 :     IntToNibble((seq & 0xFF) >> 4, &ch);
     111               0 :     outstr << ch;
     112               0 :     run_xsum += ch;
     113                 : 
     114               0 :     IntToNibble(seq & 0xF, &ch);
     115               0 :     outstr << ch;
     116               0 :     run_xsum += ch;
     117                 : 
     118               0 :     ch = ':';
     119               0 :     outstr << ch;
     120               0 :     run_xsum += ch;
     121                 :   }
     122                 : 
     123                 :   // Send the main payload
     124          230730 :   for (size_t offs = 0; offs < size; ++offs) {
     125          229825 :     ch = ptr[offs];
     126          229825 :     outstr << ch;
     127          229825 :     run_xsum += ch;
     128                 :   }
     129                 : 
     130             905 :   if (GetFlags() & DEBUG_SEND) {
     131             903 :     NaClLog(1, "TX %s\n", outstr.str().c_str());
     132                 :   }
     133                 : 
     134                 :   // Send XSUM as two nible 8bit value preceeded by '#'
     135             905 :   outstr << '#';
     136             905 :   IntToNibble((run_xsum >> 4) & 0xF, &ch);
     137             905 :   outstr << ch;
     138             905 :   IntToNibble(run_xsum & 0xF, &ch);
     139             905 :   outstr << ch;
     140                 : 
     141            1810 :   return io_->Write(outstr.str().data(),
     142            2715 :                     static_cast<int32_t>(outstr.str().length()));
     143                 : }
     144                 : 
     145                 : // Attempt to receive a packet
     146             919 : bool Session::GetPacket(Packet *pkt) {
     147                 :   char run_xsum, fin_xsum, ch;
     148             919 :   std::string in;
     149                 : 
     150                 :   // Toss characters until we see a start of command
     151             998 :   do {
     152            1013 :     if (!GetChar(&ch)) return false;
     153             998 :     in += ch;
     154                 :   } while (ch != '$');
     155                 : 
     156                 :  retry:
     157                 :   // Clear the stream
     158             904 :   pkt->Clear();
     159                 : 
     160                 :   // Prepare XSUM calc
     161             904 :   run_xsum = 0;
     162             904 :   fin_xsum = 0;
     163                 : 
     164                 :   // Stream in the characters
     165           11547 :   while (1) {
     166           12451 :     if (!GetChar(&ch)) return false;
     167                 : 
     168                 :     // If we see a '#' we must be done with the data
     169           12451 :     if (ch == '#') break;
     170                 : 
     171           11547 :     in += ch;
     172                 : 
     173                 :     // If we see a '$' we must have missed the last cmd
     174           11547 :     if (ch == '$') {
     175               0 :       NaClLog(LOG_INFO, "RX Missing $, retry.\n");
     176               0 :       goto retry;
     177                 :     }
     178                 :     // Keep a running XSUM
     179           11547 :     run_xsum += ch;
     180           11547 :     pkt->AddRawChar(ch);
     181                 :   }
     182                 : 
     183                 : 
     184                 :   // Get two Nibble XSUM
     185             904 :   if (!GetChar(&ch)) return false;
     186                 : 
     187                 :   int val;
     188             904 :   NibbleToInt(ch, & val);
     189             904 :   fin_xsum = val << 4;
     190                 : 
     191             904 :   if (!GetChar(&ch)) return false;
     192             903 :   NibbleToInt(ch, &val);
     193             903 :   fin_xsum |= val;
     194                 : 
     195             903 :   if (GetFlags() & DEBUG_RECV) NaClLog(1, "RX %s\n", in.c_str());
     196                 : 
     197             903 :   pkt->ParseSequence();
     198                 : 
     199                 :   // If ACKs are off, we are done.
     200             903 :   if (GetFlags() & IGNORE_ACK) return true;
     201                 : 
     202                 :   // If the XSUMs don't match, signal bad packet
     203             903 :   if (fin_xsum == run_xsum) {
     204             903 :     char out[3] = { '+', 0, 0 };
     205                 :     int32_t seq;
     206                 : 
     207                 :     // If we have a sequence number
     208             903 :     if (pkt->GetSequence(&seq)) {
     209                 :       // Respond with Sequence number
     210               0 :       IntToNibble(seq >> 4, &out[1]);
     211               0 :       IntToNibble(seq & 0xF, &out[2]);
     212               0 :       return io_->Write(out, 3);
     213                 :     }
     214             903 :     return io_->Write(out, 1);
     215                 :   } else {
     216                 :     // Resend a bad XSUM and look for retransmit
     217               0 :     io_->Write("-", 1);
     218                 : 
     219               0 :     NaClLog(LOG_INFO, "RX Bad XSUM, retry\n");
     220               0 :     goto retry;
     221                 :   }
     222                 : 
     223             919 :   return true;
     224                 : }
     225                 : 
     226                 : }  // End of namespace gdb_rsp
     227                 : 

Generated by: LCOV version 1.7