LCOV - code coverage report
Current view: top level - src - Gnutella.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 2 176 1.1 %
Date: 2010-12-13 Functions: 2 15 13.3 %
Branches: 2 148 1.4 %

           Branch data     Line data    Source code
       1                 :            : // $Id: Gnutella.cc 6219 2008-10-01 05:39:07Z vern $
       2                 :            : //
       3                 :            : // See the file "COPYING" in the main distribution directory for copyright.
       4                 :            : 
       5                 :            : #include "config.h"
       6                 :            : 
       7                 :            : #include <ctype.h>
       8                 :            : 
       9                 :            : #include "NetVar.h"
      10                 :            : #include "HTTP.h"
      11                 :            : #include "Gnutella.h"
      12                 :            : #include "Event.h"
      13                 :            : #include "PIA.h"
      14                 :            : 
      15                 :            : 
      16                 :          0 : GnutellaMsgState::GnutellaMsgState()
      17                 :            :         {
      18                 :          0 :         buffer = "";
      19                 :          0 :         current_offset = 0;
      20                 :          0 :         headers = "";
      21                 :          0 :         msg_hops = 0;
      22                 :          0 :         msg_len = 0;
      23                 :          0 :         msg_pos = 0;
      24                 :          0 :         msg_type = 0;
      25                 :          0 :         msg_sent = 1;
      26                 :          0 :         msg_ttl = 0;
      27                 :          0 :         payload_left = 0;
      28                 :          0 :         got_CR = 0;
      29                 :          0 :         payload_len = 0;
      30                 :          0 :         }
      31                 :            : 
      32                 :            : 
      33                 :          0 : Gnutella_Analyzer::Gnutella_Analyzer(Connection* conn)
      34                 :          0 : : TCP_ApplicationAnalyzer(AnalyzerTag::Gnutella, conn)
      35                 :            :         {
      36                 :          0 :         state = 0;
      37                 :          0 :         new_state = 0;
      38                 :          0 :         sent_establish = 0;
      39                 :            : 
      40                 :          0 :         ms = 0;
      41                 :            : 
      42                 :          0 :         orig_msg_state = new GnutellaMsgState();
      43                 :          0 :         resp_msg_state = new GnutellaMsgState();
      44                 :          0 :         }
      45                 :            : 
      46                 :          0 : void Gnutella_Analyzer::Done()
      47                 :            :         {
      48                 :          0 :         TCP_ApplicationAnalyzer::Done();
      49                 :            : 
      50   [ #  #  #  # ]:          0 :         if ( ! sent_establish && (gnutella_establish || gnutella_not_establish) )
         [ #  # ][ #  # ]
      51                 :            :                 {
      52                 :          0 :                 val_list* vl = new val_list;
      53                 :            : 
      54                 :          0 :                 vl->append(BuildConnVal());
      55                 :            : 
      56   [ #  #  #  # ]:          0 :                 if ( Established() && gnutella_establish )
                 [ #  # ]
      57                 :          0 :                         ConnectionEvent(gnutella_establish, vl);
      58 [ #  # ][ #  # ]:          0 :                 else if ( ! Established () && gnutella_not_establish )
                 [ #  # ]
      59                 :          0 :                         ConnectionEvent(gnutella_not_establish, vl);
      60                 :            :                 }
      61                 :            : 
      62         [ #  # ]:          0 :         if ( gnutella_partial_binary_msg )
      63                 :            :                 {
      64                 :          0 :                 GnutellaMsgState* p = orig_msg_state;
      65                 :            : 
      66         [ #  # ]:          0 :                 for ( int i = 0; i < 2; ++i, p = resp_msg_state )
      67                 :            :                         {
      68 [ #  # ][ #  # ]:          0 :                         if ( ! p->msg_sent && p->msg_pos )
      69                 :            :                                 {
      70                 :          0 :                                 val_list* vl = new val_list;
      71                 :            : 
      72                 :          0 :                                 vl->append(BuildConnVal());
      73                 :          0 :                                 vl->append(new StringVal(p->msg));
      74                 :          0 :                                 vl->append(new Val((i == 0), TYPE_BOOL));
      75                 :          0 :                                 vl->append(new Val(p->msg_pos, TYPE_COUNT));
      76                 :            : 
      77                 :          0 :                                 ConnectionEvent(gnutella_partial_binary_msg, vl);
      78                 :            :                                 }
      79                 :            : 
      80 [ #  # ][ #  # ]:          0 :                         else if ( ! p->msg_sent && p->payload_left )
      81                 :          0 :                                 SendEvents(p, (i == 0));
      82                 :            :                         }
      83                 :            :                 }
      84                 :          0 :         }
      85                 :            : 
      86                 :            : 
      87                 :          0 : int Gnutella_Analyzer::NextLine(const u_char* data, int len)
      88                 :            :         {
      89         [ #  # ]:          0 :         if ( ! ms )
      90                 :          0 :                 return 0;
      91                 :            : 
      92 [ #  # ][ #  # ]:          0 :         if ( Established() || ms->current_offset >= len )
                 [ #  # ]
      93                 :          0 :                 return 0;
      94                 :            : 
      95         [ #  # ]:          0 :         for ( ; ms->current_offset < len; ++ms->current_offset )
      96                 :            :                 {
      97         [ #  # ]:          0 :                 if ( data[ms->current_offset] == '\r' )
      98                 :          0 :                         ms->got_CR = 1;
      99                 :            : 
     100 [ #  # ][ #  # ]:          0 :                 else if ( data[ms->current_offset] == '\n' && ms->got_CR )
     101                 :            :                         {
     102                 :          0 :                         ms->got_CR = 0;
     103                 :          0 :                         ++ms->current_offset;
     104                 :          0 :                         return 1;
     105                 :            :                         }
     106                 :            :                 else
     107                 :          0 :                         ms->buffer += data[ms->current_offset];
     108                 :            :                 }
     109                 :            : 
     110                 :          0 :         return 0;
     111                 :            :         }
     112                 :            : 
     113                 :            : 
     114                 :          0 : int Gnutella_Analyzer::IsHTTP(string header)
     115                 :            :         {
     116         [ #  # ]:          0 :         if ( header.find(" HTTP/1.") == string::npos )
     117                 :          0 :                 return 0;
     118                 :            : 
     119         [ #  # ]:          0 :         if ( gnutella_http_notify )
     120                 :            :                 {
     121                 :          0 :                 val_list* vl = new val_list;
     122                 :            : 
     123                 :          0 :                 vl->append(BuildConnVal());
     124                 :          0 :                 ConnectionEvent(gnutella_http_notify, vl);
     125                 :            :                 }
     126                 :            : 
     127         [ #  # ]:          0 :         if ( HTTP_Analyzer::Available() )
     128                 :            :                 {
     129                 :          0 :                 Analyzer* a = new HTTP_Analyzer(Conn());
     130                 :          0 :                 Parent()->AddChildAnalyzer(a);
     131                 :            : 
     132         [ #  # ]:          0 :                 if ( Parent()->GetTag() == AnalyzerTag::TCP )
     133                 :            :                         {
     134                 :            :                         // Replay buffered data.
     135                 :          0 :                         PIA* pia = static_cast<TransportLayerAnalyzer *>(Parent())->GetPIA();
     136         [ #  # ]:          0 :                         if ( pia )
     137                 :          0 :                                 static_cast<PIA_TCP *>(pia)->ReplayStreamBuffer(a);
     138                 :            :                         }
     139                 :            : 
     140                 :          0 :                 Parent()->RemoveChildAnalyzer(this);
     141                 :            :                 }
     142                 :            : 
     143                 :          0 :         return 1;
     144                 :            :         }
     145                 :            : 
     146                 :            : 
     147                 :          0 : int Gnutella_Analyzer::GnutellaOK(string header)
     148                 :            :         {
     149         [ #  # ]:          0 :         if ( strncmp("GNUTELLA", header.data(), 8) )
     150                 :          0 :                 return 0;
     151                 :            : 
     152                 :          0 :         int codepos = header.find(' ') + 1;
     153         [ #  # ]:          0 :         if ( ! strncmp("200", header.data() + codepos, 3) )
     154                 :          0 :                 return 1;
     155                 :            : 
     156                 :          0 :         return 0;
     157                 :            :         }
     158                 :            : 
     159                 :            : 
     160                 :          0 : void Gnutella_Analyzer::DeliverLines(int len, const u_char* data, bool orig)
     161                 :            :         {
     162         [ #  # ]:          0 :         if ( ! ms )
     163                 :          0 :                 return;
     164                 :            : 
     165         [ #  # ]:          0 :         while ( NextLine(data, len) )
     166                 :            :                 {
     167         [ #  # ]:          0 :                 if ( ms->buffer.length() )
     168                 :            :                         {
     169         [ #  # ]:          0 :                         if ( ms->headers.length() == 0 )
     170                 :            :                                 {
     171         [ #  # ]:          0 :                                 if ( IsHTTP(ms->buffer) )
     172                 :          0 :                                         return;
     173         [ #  # ]:          0 :                                 if ( GnutellaOK(ms->buffer) )
     174                 :            :                                         new_state |=
     175         [ #  # ]:          0 :                                                 orig ? ORIG_OK : RESP_OK;
     176                 :            :                                 }
     177                 :            : 
     178                 :          0 :                         ms->headers = ms->headers + "\r\n" + ms->buffer;
     179                 :          0 :                         ms->buffer = "";
     180                 :            :                         }
     181                 :            :                 else
     182                 :            :                         {
     183         [ #  # ]:          0 :                         if ( gnutella_text_msg )
     184                 :            :                                 {
     185                 :          0 :                                 val_list* vl = new val_list;
     186                 :            : 
     187                 :          0 :                                 vl->append(BuildConnVal());
     188                 :          0 :                                 vl->append(new Val(orig, TYPE_BOOL));
     189                 :          0 :                                 vl->append(new StringVal(ms->headers.data()));
     190                 :            : 
     191                 :          0 :                                 ConnectionEvent(gnutella_text_msg, vl);
     192                 :            :                                 }
     193                 :            : 
     194                 :          0 :                         ms->headers = "";
     195                 :          0 :                         state |= new_state;
     196                 :            : 
     197   [ #  #  #  # ]:          0 :                         if ( Established () && gnutella_establish )
                 [ #  # ]
     198                 :            :                                 {
     199                 :          0 :                                 val_list* vl = new val_list;
     200                 :            : 
     201                 :          0 :                                 sent_establish = 1;
     202                 :          0 :                                 vl->append(BuildConnVal());
     203                 :            : 
     204                 :          0 :                                 ConnectionEvent(gnutella_establish, vl);
     205                 :            :                                 }
     206                 :            :                         }
     207                 :            :                 }
     208                 :            :         }
     209                 :            : 
     210                 :          0 : void Gnutella_Analyzer::DissectMessage(char* msg)
     211                 :            :         {
     212         [ #  # ]:          0 :         if ( ! ms )
     213                 :          0 :                 return;
     214                 :            : 
     215                 :          0 :         ms->msg_type = msg[16];
     216                 :          0 :         ms->msg_ttl = msg[17];
     217                 :          0 :         ms->msg_hops = msg[18];
     218                 :            : 
     219                 :          0 :         memcpy(&ms->msg_len, &msg[19], 4);
     220                 :            :         }
     221                 :            : 
     222                 :            : 
     223                 :          0 : void Gnutella_Analyzer::SendEvents(GnutellaMsgState* p, bool is_orig)
     224                 :            :         {
     225         [ #  # ]:          0 :         if ( p->msg_sent )
     226                 :          0 :                 return;
     227                 :            : 
     228         [ #  # ]:          0 :         if ( gnutella_binary_msg )
     229                 :            :                 {
     230                 :          0 :                 val_list* vl = new val_list;
     231                 :            : 
     232                 :          0 :                 vl->append(BuildConnVal());
     233                 :          0 :                 vl->append(new Val(is_orig, TYPE_BOOL));
     234                 :          0 :                 vl->append(new Val(p->msg_type, TYPE_COUNT));
     235                 :          0 :                 vl->append(new Val(p->msg_ttl, TYPE_COUNT));
     236                 :          0 :                 vl->append(new Val(p->msg_hops, TYPE_COUNT));
     237                 :          0 :                 vl->append(new Val(p->msg_len, TYPE_COUNT));
     238                 :          0 :                 vl->append(new StringVal(p->payload));
     239                 :          0 :                 vl->append(new Val(p->payload_len, TYPE_COUNT));
     240                 :            :                 vl->append(new Val((p->payload_len <
     241                 :            :                                     min(p->msg_len, GNUTELLA_MAX_PAYLOAD)),
     242                 :          0 :                                    TYPE_BOOL));
     243                 :          0 :                 vl->append(new Val((p->payload_left == 0), TYPE_BOOL));
     244                 :            : 
     245                 :          0 :                 ConnectionEvent(gnutella_binary_msg, vl);
     246                 :            :                 }
     247                 :            :         }
     248                 :            : 
     249                 :            : 
     250                 :          0 : void Gnutella_Analyzer::DeliverMessages(int len, const u_char* data, bool orig)
     251                 :            :         {
     252         [ #  # ]:          0 :         if ( ! ms )
     253                 :          0 :                 return;
     254                 :            : 
     255         [ #  # ]:          0 :         while ( ms->current_offset < len )
     256                 :            :                 {
     257                 :          0 :                 ms->msg_sent = 0;
     258                 :            : 
     259                 :          0 :                 unsigned int bytes_left = len - ms->current_offset;
     260                 :          0 :                 unsigned int needed = 0;
     261                 :            : 
     262         [ #  # ]:          0 :                 if ( ms->msg_pos )
     263                 :          0 :                         needed = GNUTELLA_MSG_SIZE - ms->msg_pos;
     264                 :            : 
     265 [ #  # ][ #  # ]:          0 :                 if ( (! ms->msg_pos && ! ms->payload_left &&
         [ #  # ][ #  # ]
                 [ #  # ]
     266                 :            :                       (bytes_left >= GNUTELLA_MSG_SIZE)) ||
     267                 :            :                      (ms->msg_pos && (bytes_left >= needed)) )
     268                 :            :                         {
     269         [ #  # ]:          0 :                         int sz = ms->msg_pos ? needed : GNUTELLA_MSG_SIZE;
     270                 :            : 
     271                 :            :                         memcpy(&ms->msg[ms->msg_pos],
     272                 :          0 :                                 &data[ms->current_offset], sz);
     273                 :            : 
     274                 :          0 :                         ms->current_offset += sz;
     275                 :          0 :                         DissectMessage(ms->msg);
     276                 :          0 :                         ms->payload_left = ms->msg_len;
     277                 :          0 :                         ms->msg_pos = 0;
     278         [ #  # ]:          0 :                         if ( ms->msg_len == 0 )
     279                 :          0 :                                 SendEvents(ms, orig);
     280                 :            :                         }
     281                 :            : 
     282 [ #  # ][ #  # ]:          0 :                 else if ( (! ms->msg_pos && ! ms->payload_left &&
         [ #  # ][ #  # ]
                 [ #  # ]
     283                 :            :                            (bytes_left < GNUTELLA_MSG_SIZE)) ||
     284                 :            :                           (ms->msg_pos && (bytes_left < needed)) )
     285                 :            :                         {
     286                 :            :                         memcpy(&ms->msg[ms->msg_pos], &data[ms->current_offset],
     287                 :          0 :                                 bytes_left);
     288                 :          0 :                         ms->current_offset += bytes_left;
     289                 :          0 :                         ms->msg_pos += bytes_left;
     290                 :            :                         }
     291                 :            : 
     292         [ #  # ]:          0 :                 else if ( ms->payload_left )
     293                 :            :                         {
     294                 :            :                         unsigned int space =
     295                 :            :                                 ms->payload_len >= GNUTELLA_MAX_PAYLOAD ?
     296         [ #  # ]:          0 :                                         0 : GNUTELLA_MAX_PAYLOAD - ms->payload_len;
     297                 :            :                         unsigned int sz =
     298         [ #  # ]:          0 :                                 (bytes_left < space) ? bytes_left : space;
     299                 :            : 
     300         [ #  # ]:          0 :                         if ( space )
     301                 :            :                                 {
     302                 :            :                                 memcpy(&ms->payload[ms->payload_len],
     303                 :          0 :                                         &data[ms->current_offset], sz);
     304                 :          0 :                                 ms->payload_len += sz;
     305                 :            :                                 }
     306                 :            : 
     307         [ #  # ]:          0 :                         if ( ms->payload_left > bytes_left )
     308                 :            :                                 {
     309                 :          0 :                                 ms->current_offset += bytes_left;
     310                 :          0 :                                 ms->payload_left -= bytes_left;
     311                 :            :                                 }
     312                 :            :                         else
     313                 :            :                                 {
     314                 :          0 :                                 ms->current_offset += ms->payload_left;
     315                 :          0 :                                 ms->payload_left = 0;
     316                 :          0 :                                 SendEvents(ms, orig);
     317                 :            :                                 }
     318                 :            :                         }
     319                 :            :                 }
     320                 :            :         }
     321                 :            : 
     322                 :            : 
     323                 :          0 : void Gnutella_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
     324                 :            :         {
     325                 :          0 :         TCP_ApplicationAnalyzer::DeliverStream(len, data, orig);
     326                 :            : 
     327         [ #  # ]:          0 :         ms = orig ? orig_msg_state : resp_msg_state;
     328                 :          0 :         ms->current_offset = 0;
     329         [ #  # ]:          0 :         if ( ! Established() )
     330                 :            :                 {
     331                 :          0 :                 DeliverLines(len, data, orig);
     332                 :            : 
     333   [ #  #  #  # ]:          0 :                 if ( Established() && ms->current_offset < len &&
         [ #  # ][ #  # ]
     334                 :            :                           gnutella_binary_msg )
     335                 :          0 :                         DeliverMessages(len, data, orig);
     336                 :            :                 }
     337                 :            : 
     338         [ #  # ]:          0 :         else if ( gnutella_binary_msg )
     339                 :          0 :                 DeliverMessages(len, data, orig);
     340 [ +  - ][ +  - ]:          6 :         }
     341                 :          3 : 

Generated by: LCOV version 1.8