Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

wvprotostream.cc

Go to the documentation of this file.
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * WvProtoStream is a framework that makes it easy to communicate using 00006 * common command-response driven protocols. This is supposed to be flexible 00007 * enough to handle FTP, HTTP, SMTP, tunnelv, Weaver rcmd, and many others. 00008 */ 00009 #include "wvprotostream.h" 00010 #include "wvlog.h" 00011 #include "strutils.h" 00012 #include <ctype.h> 00013 #include <assert.h> 00014 00015 00016 WvProtoStream::WvProtoStream(WvStream *_cloned, WvLog *_debuglog) 00017 : WvStreamClone(_cloned) 00018 { 00019 if (_debuglog) 00020 logp = new WvLog(_debuglog->split(WvLog::Debug4)); 00021 else 00022 logp = NULL; 00023 00024 log_enable = true; 00025 state = 0; 00026 } 00027 00028 00029 WvProtoStream::~WvProtoStream() 00030 { 00031 close(); 00032 if (logp) delete logp; 00033 } 00034 00035 00036 /* Just like a WvStream::uwrite(), but it copies all output to WvLog if 00037 * log_enable==true. 00038 */ 00039 size_t WvProtoStream::uwrite(const void *buf, size_t size) 00040 { 00041 if (logp && log_enable) 00042 { 00043 (*logp)("Sent: "); 00044 logp->write(buf, size); 00045 (*logp)("\n"); 00046 } 00047 00048 return WvStreamClone::uwrite(buf, size); 00049 } 00050 00051 00052 WvProtoStream::Token *WvProtoStream::next_token() 00053 { 00054 static unsigned char whitespace[] = " \t\r\n"; 00055 size_t len; 00056 00057 // find and remove up to first non-whitespace 00058 tokbuf.get(tokbuf.match(whitespace, sizeof(whitespace))); 00059 00060 // return a token up to the first whitespace character 00061 len = tokbuf.notmatch(whitespace, sizeof(whitespace)); 00062 return len ? new Token(tokbuf.get(len), len) : NULL; 00063 } 00064 00065 00066 WvString WvProtoStream::next_token_str() 00067 { 00068 Token *t = next_token(); 00069 if (!t) return WvString(""); 00070 00071 WvString s(t->data); 00072 delete t; 00073 return s; 00074 } 00075 00076 00077 WvString WvProtoStream::token_remaining() 00078 { 00079 tokbuf.put('\0'); 00080 return trim_string((char *)tokbuf.get(tokbuf.used())); 00081 } 00082 00083 00084 /* Default input tokenizer. "line" is NULL-terminated, and individual string 00085 * tokens are separated by any amount of whitespace. 00086 */ 00087 WvProtoStream::TokenList *WvProtoStream::tokenize() 00088 { 00089 TokenList *tl = new TokenList; 00090 Token *t; 00091 00092 while ((t = next_token()) != NULL) 00093 tl->append(t, true); 00094 #if 0 00095 if (logp && log_enable && tl->count()) 00096 { 00097 (*logp)("Read: "); 00098 TokenList::Iter i(*tl); 00099 for (i.rewind(); i.next(); ) 00100 (*logp)("(%s) ", i.data); 00101 (*logp)("\n"); 00102 } 00103 #endif 00104 return tl; 00105 } 00106 00107 00108 /* convert a TokenList to an array of Token. 00109 * The TokenList becomes invalid after this operation! 00110 * Remember to free the array afterwards! 00111 */ 00112 size_t WvProtoStream::list_to_array(TokenList *tl, Token **array) 00113 { 00114 size_t total = tl->count(), count; 00115 00116 assert(array); 00117 *array = new Token[total]; 00118 00119 TokenList::Iter i(*tl); 00120 for (count = 0, i.rewind(); i.next(); count++) 00121 { 00122 Token &t = *i; 00123 (*array)[count].fill((unsigned char *)(const char *)t.data, t.length); 00124 } 00125 00126 delete tl; 00127 return count; 00128 } 00129 00130 00131 /* Retrieve an input line and parse its first token. 00132 * This is the usual high-level interface to the input tokenizer. Remember 00133 * to free the array afterwards! 00134 * Ths input line is specifically allowed to be a NULL pointer. In that case, 00135 * the returned token will be NULL also. 00136 */ 00137 WvProtoStream::Token *WvProtoStream::tokline(const char *line) 00138 { 00139 if (!line) return NULL; 00140 00141 char *newline = strdup(line); 00142 00143 tokbuf.zap(); 00144 tokbuf.put(line, strlen(line)); 00145 00146 if (strlen(trim_string(newline)) > 0) 00147 (*logp)("Read: %s\n", trim_string(newline)); 00148 00149 free(newline); 00150 00151 return next_token(); 00152 } 00153 00154 00155 /* returns -1 if t is not in lookup[], or else the index into lookup where 00156 * the token was found. 00157 */ 00158 int WvProtoStream::tokanal(const Token &t, char **lookup, 00159 bool case_sensitive) 00160 { 00161 assert(lookup); 00162 00163 char **i; 00164 00165 for (i = lookup; *i; i++) 00166 { 00167 if ( (!case_sensitive && !strcasecmp(t.data, *i)) 00168 || ( case_sensitive && !strcmp(t.data, *i)) ) 00169 return i - lookup; 00170 } 00171 00172 return -1; 00173 } 00174 00175 00176 void WvProtoStream::do_state(Token &) 00177 { 00178 } 00179 00180 00181 void WvProtoStream::switch_state(int newstate) 00182 { 00183 state = newstate; 00184 } 00185 00186 00187 /* Default execute() function -- process a line of input, and handle it 00188 * (based on the current system state) using do_state(). 00189 */ 00190 void WvProtoStream::execute() 00191 { 00192 WvStreamClone::execute(); 00193 00194 Token *t1 = tokline(getline(0)); 00195 00196 if (t1) 00197 { 00198 do_state(*t1); 00199 delete t1; 00200 } 00201 } 00202 00203 00204 00205 //////////////////////////////////// WvProtoStream::Token 00206 00207 00208 00209 WvProtoStream::Token::Token() 00210 { 00211 // leave empty -- you should call fill() manually later! 00212 } 00213 00214 00215 WvProtoStream::Token::Token(const unsigned char *_data, size_t _length) 00216 { 00217 fill(_data, _length); 00218 } 00219 00220 00221 void WvProtoStream::Token::fill(const unsigned char *_data, 00222 size_t _length) 00223 { 00224 length = _length; 00225 00226 data.setsize(length + 1); 00227 memcpy(data.edit(), _data, length); 00228 data.edit()[length] = 0; 00229 } 00230 00231 00232 WvProtoStream::Token::~Token() 00233 { 00234 // 'data' member is freed automatically 00235 }

Generated on Tue Oct 5 01:09:20 2004 for WvStreams by doxygen 1.3.7