protocol_stream.cpp
上传用户:psq1974
上传日期:2007-01-06
资源大小:1195k
文件大小:8k
源码类别:

mpeg/mp3

开发平台:

C/C++

  1. /* Copyright (C) 1998, 1999 State University of New York at Stony Brook
  2.    Author: Andrew V. Shuvalov ( andrew@ecsl.cs.sunysb.edu )
  3.    Software license is located in file "COPYING"
  4. */
  5. #include "stdafx.h"
  6. #include "protocol_stream.h"
  7. #include "exceptions.h"
  8. #include "../../pusher/src/timeval.h"
  9. const char protocol_stream::prompt[] = ">>>";
  10. const char protocol_stream::command[] = "command";
  11. protocol_stream::protocol_stream( SOCKET _s, int gen_timeout ) 
  12.   : sock( _s ), everything_read( false ), input_buffer_offset( 0 ),
  13.     input_buffer_end( 0 ), genericTimeout( gen_timeout * 1000 )
  14. {
  15. }
  16. bool protocol_stream::test_for_input( int millisec )
  17. {
  18.   fd_set set;
  19.   FD_ZERO( &set );
  20.   FD_SET( sock, &set );
  21.   Timeval diff( 0, millisec * 1000 );
  22.   int ret = select( FD_SETSIZE, &set, NULL, NULL, &diff.val() );
  23.   if( ret == -1 )
  24.     throw NetworkException( "select: %s", sys_errlist[ errno ] );
  25.   if( !ret )  // timeval expires
  26.     return false;
  27.   return true;
  28. }
  29. bool protocol_stream::test_for_any_pending_input( int millisec )
  30. {
  31. # ifdef WIN32
  32.   if( !buffer_is_empty() )
  33.     return true;
  34. # else
  35. # endif
  36.   if( test_for_input( millisec ))
  37.     return true;
  38.   return false;
  39. }
  40. bool protocol_stream::buffer_is_empty()
  41. {
  42.   if( input_buffer_offset < input_buffer_end )
  43.     return false;
  44.   return true;
  45. }
  46. bool protocol_stream::eof()
  47. {
  48.   return false;
  49. }
  50. int protocol_stream::peek()
  51. {
  52.   if( !buffer_is_empty() )
  53.     return (unsigned) input_buffer[ input_buffer_offset ];
  54.   // buffer is empty - move marker to start
  55.   input_buffer_offset = 0;
  56.   input_buffer_end = 0;
  57.   // buffer is empty - read a little
  58.   // freeze for a while...
  59.   if( !test_for_input( genericTimeout ) )
  60.     return -1;
  61.   // read
  62.   int res = recv( sock, input_buffer, sizeof( input_buffer ), 0 );
  63.   if( res > 0 )
  64.     {
  65.       input_buffer_end = res;
  66.       // put zero at the end..
  67.       input_buffer[ input_buffer_end ] = '';
  68.       return (unsigned) input_buffer[ input_buffer_offset ];
  69.     }
  70.   // error
  71.   return -1;
  72. }
  73. int protocol_stream::get( char &location )
  74. {
  75.   int ch = peek();
  76.   if( ch == -1 )
  77.     {
  78.       location = '';
  79.       return -1;
  80.     }
  81.   // copy value to location
  82.   location = input_buffer[ input_buffer_offset ];
  83.   input_buffer_offset ++;
  84.   return ch;
  85. }
  86. #ifdef WIN32 // for poor OS's
  87. char *protocol_stream::getline( char *buf, unsigned size )
  88. {
  89.   // default:
  90.   *buf = '';
  91.   *( input_buffer + input_buffer_end ) = '';
  92.   // de we have something in buffer?
  93.   if( !buffer_is_empty() )
  94.     {
  95.       // find 'n' 
  96.       char *ptr = strchr( input_buffer + input_buffer_offset, 'n' );
  97.       if( ptr )
  98. {
  99.   // we have found end-of-line
  100.   unsigned register size_to_copy = ptr - input_buffer 
  101.     - input_buffer_offset;
  102.   if( size_to_copy > size )
  103.     size_to_copy = size;
  104.   memcpy( buf, input_buffer + input_buffer_offset, size_to_copy );
  105.   // and zero at the end...
  106.   buf[ size_to_copy ] = '';
  107.   // we must skip the 'n' as well
  108.   input_buffer_offset += size_to_copy + 1;
  109.   return buf;
  110. }
  111.       else
  112. {
  113.   // no end-of-line, we may try to hold for a second and read from 
  114.   // the network
  115.   // first check if buffer must be moved:
  116.   if( input_buffer_offset >= sizeof( input_buffer ) / 2 )
  117.     {
  118.       memcpy( input_buffer, input_buffer + input_buffer_offset,
  119.       input_buffer_end - input_buffer_offset );
  120.       input_buffer_end = input_buffer_end - input_buffer_offset;
  121.       input_buffer_offset = 0;
  122.     }
  123.   // this call is recursive, so it must have a dalay inside
  124.   if( test_for_input( 100 ) )
  125.     {
  126.       // we have data
  127.       int res = recv( sock, input_buffer + input_buffer_end, 
  128.       sizeof( input_buffer ) - 
  129.       (input_buffer_end - input_buffer_offset), 0 );
  130.       if( res > 0 )
  131. {
  132.   input_buffer_end += res;
  133.   // put zero at the end..
  134.   input_buffer[ input_buffer_end ] = '';
  135.   // we have new data, try to recursively call itself
  136.   return getline( buf, size );
  137. }
  138.       if( res < 0 )
  139. {
  140.   // error
  141.   return NULL;
  142. }
  143.     }
  144.   // nothing.. maybe we reached prompt?
  145.   char *ptr = strstr( input_buffer + input_buffer_offset, prompt );
  146.   if( ptr )
  147.     {
  148.       // prompt reached
  149.       unsigned register size_to_copy = ptr - 
  150. (input_buffer + input_buffer_offset) + sizeof( prompt ) - 1;
  151.       if( size_to_copy > size )
  152. size_to_copy = size;
  153.       memcpy( buf, input_buffer + input_buffer_offset, size_to_copy );
  154.       
  155.       input_buffer_offset += size_to_copy;
  156.       return buf;
  157.     }
  158. } // if( ptr )
  159.     } // if( !buffer_is_empty() )
  160.   else
  161.     {
  162.       // buffer is empty - reset pointers
  163.       input_buffer_offset = 0;
  164.       input_buffer_end = 0;
  165.       // buffer is empty - read a little
  166.       // freeze for a while...
  167.       if( !test_for_input( genericTimeout ) )
  168. return NULL;
  169.       // read
  170.       int res = recv( sock, input_buffer, sizeof( input_buffer ), 0 );
  171.       if( res > 0 )
  172. {
  173.   input_buffer_end = res;
  174.   // put zero at the end..
  175.   input_buffer[ input_buffer_end ] = '';
  176.   // and call itself recursively
  177.   return getline( buf, size );
  178. }
  179.       if( res < 0 )
  180. throw NetworkException( "recv: %s", sys_errlist[ errno ] );
  181.     }
  182.   return buf;
  183. }
  184. #endif
  185. protocol_stream& protocol_stream::operator >>( std::string &s )
  186. {
  187.   if( everything_read ) {
  188.     s = "";
  189.     return *this;
  190.   }
  191.   char buf[1024];
  192.   if( before_mark ) 
  193.     {
  194.       // load until mark
  195.       while( !eof() )
  196. {
  197.   getline( buf, sizeof( buf ));
  198.   if( !buf[0] )
  199.     continue;
  200.   if( buf[0] == '#' ) {
  201.     messages.push_back( s );
  202.     continue;
  203.   }
  204.   if( !strcmp( buf, "->" )) {
  205.     before_mark = false;
  206.     break;
  207.   }
  208. }
  209.       if( everything_read ) {
  210. s = "";
  211. return *this;
  212.       }
  213.     }
  214.   while( !eof() )
  215.     {
  216.       getline( buf, sizeof( buf ));
  217.       // check for special messages, which may indicate error
  218.       if( !s.compare( "#!disconnect" ))
  219. throw ProtocolException( "disconnected" );
  220.       if( buf[0] == '#' ) {
  221. messages.push_back( s );
  222. continue;
  223.       }
  224.       if( !strcmp( buf, "<-" )) {
  225. skip_to_prompt();
  226. everything_read = true;
  227. break;
  228.       }
  229.       s = buf;
  230.       s.c_str();   // terminate
  231.       // cout << s << endl;
  232.       return *this;
  233.     }
  234.   s = "";
  235.   s.c_str();   // terminate
  236.   return *this;
  237. }
  238. protocol_stream& protocol_stream::operator >>( int &value )
  239. {
  240.   std::string s;
  241.   *this >> s;
  242.   value = atoi( s.c_str() );
  243.   return *this;
  244. }
  245. protocol_stream& protocol_stream::operator >>
  246. ( std::vector< std::string > &lines )
  247. {
  248.   wait_input();
  249.   while( true )
  250.     {
  251.       std::string s;
  252.       *this >> s;
  253.       
  254.       if( everything_read )
  255. break;
  256.       lines.push_back( s );
  257.     }
  258.   return *this;
  259. }
  260. protocol_stream& protocol_stream::operator <<( const std::string &s )
  261. {
  262.   const char *str = s.c_str();
  263.   send( sock, str, s.length(), 0 );
  264.   // confirmation is mandatory
  265.   wait_input();
  266.   return *this;
  267. }
  268. void protocol_stream::skip_to_prompt()
  269. {
  270.   char buf[ 1024 ];
  271.   // nothing to do
  272.   if( everything_read ) {
  273.     return;
  274.   }
  275.   while( !eof() )
  276.     {
  277.       int ch = peek();
  278.       if( ch == -1 )
  279. break;
  280.       if( ch != '>' )
  281. {
  282.   getline( buf, sizeof( buf ));
  283.   if( !buf[0] )
  284.     continue;
  285.   if( ch == '#' ) {
  286.     std::string s( buf );
  287.     messages.push_back( s );
  288.   }
  289. }
  290.       else  // input char by char
  291. {
  292.   for( int i = 0; i < 3; i++ )
  293.     get( buf[i] );
  294.   buf[3] = '';
  295.   std::string s( buf );
  296.   if( !s.length() )
  297.     continue;
  298.   if( !s.compare( prompt )) 
  299.     {
  300.       // and set the flag that we don't expect any input anymore..
  301.       everything_read = true;
  302.       break;
  303.     }
  304.   // ups! this is not our string... append the end of string
  305.   getline( buf + 3, sizeof( buf ) - 3 );
  306. }
  307.     }
  308. }
  309. void protocol_stream::skip_to_prompt( std::vector< std::string > &msgs )
  310. {
  311.   skip_to_prompt();
  312.   append_messages( msgs );
  313. }
  314.   
  315. void protocol_stream::append_messages( std::vector< std::string > &msgs )
  316. {
  317.   if( !messages.empty() )
  318.     msgs.insert( msgs.end(), messages.begin(), messages.end() );
  319.   messages.clear();
  320. }