Vidalia 0.2.15
Stream.cpp
Go to the documentation of this file.
00001 /*
00002 **  This file is part of Vidalia, and is subject to the license terms in the
00003 **  LICENSE file, found in the top level directory of this distribution. If 
00004 **  you did not receive the LICENSE file with this file, you may obtain it
00005 **  from the Vidalia source package distributed by the Vidalia Project at
00006 **  http://www.torproject.org/projects/vidalia.html. No part of Vidalia, 
00007 **  including this file, may be copied, modified, propagated, or distributed 
00008 **  except according to the terms described in the LICENSE file.
00009 */
00010 
00011 /* 
00012 ** \file Stream.cpp
00013 ** \brief Object representing a Tor stream
00014 */
00015 
00016 #include "Stream.h"
00017 #include "Circuit.h" 
00018 
00019 #include <QStringList>
00020 
00021 
00022 /** Default constructor. */
00023 Stream::Stream()
00024 {
00025   _status    = Unknown;
00026   _port      = 0;
00027 }
00028 
00029 /** Constructor */
00030 Stream::Stream(const StreamId &streamId, Status status,
00031                const CircuitId &circuitId, const QString &address,
00032                quint16 port)
00033 {
00034   _streamId  = streamId;
00035   _status    = status;
00036   _circuitId = circuitId;
00037   _address   = address;
00038   _port      = port;
00039 }
00040 
00041 /** Constructor */
00042 Stream::Stream(const StreamId &streamId, Status status,
00043                const CircuitId &circuitId, const QString &target)
00044 {
00045   _streamId  = streamId;
00046   _status    = status;
00047   _circuitId = circuitId;
00048   _port      = 0;
00049 
00050   int i = target.indexOf(":");
00051   if (i >= 0)
00052     _address = target.mid(0, i);
00053   if (i + 1 < target.length()) 
00054     _port = target.mid(i+1).toUInt();
00055 }
00056 
00057 /** Parses the given string for stream information, given in Tor control
00058  * protocol format. The format is:
00059  *
00060  *     StreamID SP StreamStatus SP CircID SP Target
00061  */
00062 Stream
00063 Stream::fromString(const QString &stream)
00064 {
00065   QStringList parts = stream.split(" ", QString::SkipEmptyParts);
00066   if (parts.size() >= 4) { 
00067     /* Get the stream ID */
00068     StreamId streamId = parts.at(0);
00069     /* Get the stream status value */
00070     Stream::Status status = Stream::toStatus(parts.at(1));
00071     /* Get the ID of the circuit on which this stream travels */
00072     CircuitId circId = parts.at(2);
00073     /* Get the target address for this stream */
00074     QString target = parts.at(3);
00075     
00076     return Stream(streamId, status, circId, target);
00077   }
00078   return Stream();
00079 }
00080 
00081 /** Returns true iff <b>streamId</b> consists of only between 1 and 16
00082  * (inclusive) ASCII-encoded letters and numbers. */
00083 bool
00084 Stream::isValidStreamId(const StreamId &streamId)
00085 {
00086   int length = streamId.length();
00087   if (length < 1 || length > 16)
00088     return false;
00089 
00090   for (int i = 0; i < length; i++) {
00091     char c = streamId[i].toAscii();
00092     if (c < '0' && c > '9' && c < 'A' && c > 'Z' && c < 'a' && c > 'z')
00093       return false;
00094   }
00095   return true;
00096 }
00097 
00098 /** Converts a string description of a stream's status to its enum value */
00099 Stream::Status
00100 Stream::toStatus(const QString &strStatus)
00101 {
00102   if (!strStatus.compare("NEW", Qt::CaseInsensitive))
00103     return New;
00104   if (!strStatus.compare("NEWRESOLVE", Qt::CaseInsensitive))
00105     return NewResolve;
00106   if (!strStatus.compare("SENTCONNECT", Qt::CaseInsensitive))
00107     return SentConnect;
00108   if (!strStatus.compare("SENTRESOLVE", Qt::CaseInsensitive))
00109     return SentResolve;
00110   if (!strStatus.compare("SUCCEEDED", Qt::CaseInsensitive))
00111     return Succeeded;
00112   if (!strStatus.compare("FAILED", Qt::CaseInsensitive))
00113     return Failed;
00114   if (!strStatus.compare("CLOSED", Qt::CaseInsensitive))
00115     return Closed;
00116   if (!strStatus.compare("DETACHED", Qt::CaseInsensitive))
00117     return Detached;
00118   if (!strStatus.compare("REMAP", Qt::CaseInsensitive))
00119     return Remap;
00120   return Unknown;
00121 }
00122 
00123 /** Returns a human-understandable string representation of this 
00124  * stream's status. */
00125 QString
00126 Stream::statusString() const
00127 {
00128   QString status;
00129   switch (_status) {
00130     case New:           status = tr("New"); break;
00131     case NewResolve:    
00132     case SentResolve:   status = tr("Resolving"); break;
00133     case SentConnect:   status = tr("Connecting"); break;
00134     case Succeeded:     status = tr("Open"); break;
00135     case Failed:        status = tr("Failed"); break;
00136     case Closed:        status = tr("Closed"); break;
00137     case Detached:      status = tr("Retrying"); break;
00138     case Remap:         status = tr("Remapped"); break;
00139     default:            status = tr("Unknown"); break;
00140   }
00141   return status;
00142 }
00143 
00144 /** Returns true if all fields in this Stream object are valid. */
00145 bool
00146 Stream::isValid() const
00147 {
00148   return (isValidStreamId(_streamId)
00149             && Circuit::isValidCircuitId(_circuitId)
00150             && (_status != Unknown) 
00151             && !_address.isEmpty());
00152 }
00153