00001 #ifndef CROMP_TRANSACTION_IMPLEMENTATION_FILE
00002 #define CROMP_TRANSACTION_IMPLEMENTATION_FILE
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "cromp_transaction.h"
00019
00020 #include <basis/log_base.h>
00021 #include <basis/mutex.h>
00022 #include <basis/portable.h>
00023 #include <data_struct/static_memory_gremlin.h>
00024 #include <octopus/entity_defs.h>
00025 #include <octopus/infoton.h>
00026 #include <loggers/file_logger.h>
00027 #include <sockets/definitions_sockets.h>
00028 #include <textual/parser_bits.h>
00029
00030 #include <stdio.h>
00031
00032 using namespace basis;
00033
00034
00035
00036
00037 const int MAXIMUM_TRANSACTION = 100 * MEGABYTE;
00038
00039
00040
00041 #undef LOG
00042 #ifdef DEBUG_CROMP_TRANSACTION
00043
00044
00045
00046 #define LOG(s) CLASS_EMERGENCY_LOG(file_logger(portable::env_string("TMP") + "/cromp_transaction.log"), s)
00047 #else
00048 #define LOG(s)
00049 #endif
00050
00051 SAFE_STATIC(mutex, __cromp_transaction_lock, )
00052
00053 cromp_transaction::~cromp_transaction()
00054 {}
00055
00056 const char *cromp_transaction::outcome_name(const outcome &to_name)
00057 {
00058 switch (to_name.value()) {
00059 case WAY_TOO_SMALL: return "WAY_TOO_SMALL";
00060 case ILLEGAL_LENGTH: return "ILLEGAL_LENGTH";
00061 default: return communication_commons::outcome_name(to_name);
00062 }
00063 }
00064
00065 byte_array &cromp_name_array()
00066 {
00067 static byte_array _hidden_cromp_array;
00068 static bool _initted = false;
00069 if (!_initted) {
00070 auto_synchronizer l(__cromp_transaction_lock());
00071
00072 if (!_initted) {
00073
00074 attach(_hidden_cromp_array, byte('c'));
00075 attach(_hidden_cromp_array, byte('r'));
00076 attach(_hidden_cromp_array, byte('o'));
00077 attach(_hidden_cromp_array, byte('m'));
00078 attach(_hidden_cromp_array, byte('p'));
00079 attach(_hidden_cromp_array, byte('!'));
00080
00081 for (int i = 0; i < 8; i++)
00082 attach(_hidden_cromp_array, byte('?'));
00083 _initted = true;
00084 }
00085 }
00086 return _hidden_cromp_array;
00087 }
00088
00089 int cromp_transaction::minimum_flat_size(const octopus_request_id &id)
00090 {
00091 return cromp_name_array().length()
00092 + id.packed_size();
00093 }
00094
00095 int cromp_transaction::minimum_flat_size(const string_array &classifier,
00096 const octopus_request_id &id)
00097 {
00098 return minimum_flat_size(id)
00099 + infoton::fast_pack_overhead(classifier);
00100
00101 }
00102
00103 void cromp_transaction::flatten(byte_array &packed_form,
00104 const infoton &request, const octopus_request_id &id)
00105 {
00106 FUNCDEF("pack");
00107 int posn = packed_form.length();
00108
00109
00110 packed_form += cromp_name_array();
00111
00112
00113
00114 id.pack(packed_form);
00115
00116
00117 infoton::fast_pack(packed_form, request);
00118 #ifdef DEBUG_CROMP_TRANSACTION
00119
00120 byte_array temp_holding;
00121 infoton::fast_pack(temp_holding, request);
00122 #endif
00123
00124
00125
00126
00127 isprintf len_string("%08x", packed_form.length() - posn);
00128 #ifdef DEBUG_CROMP_TRANSACTION
00129 LOG(isprintf("len string is %s", len_string.s()));
00130 #endif
00131 for (int j = 6; j < 14; j++)
00132 packed_form[posn + j] = byte(len_string[j - 6]);
00133
00134 #ifdef DEBUG_CROMP_TRANSACTION
00135 byte_array copy = packed_form.subarray(posn, packed_form.last());
00136 byte_array tempo;
00137 octopus_request_id urfid;
00138 if (!cromp_transaction::unflatten(copy, tempo, urfid))
00139 continuable_error(static_class_name(), func,
00140 "failed to unpack what we just packed.");
00141 else if (urfid != id)
00142 continuable_error(static_class_name(), func, "wrong id after unpack.");
00143 else if (tempo != temp_holding)
00144 continuable_error(static_class_name(), func, "wrong data after unpack.");
00145 #endif
00146
00147 }
00148
00149 bool cromp_transaction::unflatten(byte_array &packed_form,
00150 byte_array &still_flat, octopus_request_id &req_id)
00151 {
00152 FUNCDEF("unflatten");
00153 still_flat.reset();
00154 int len = 0;
00155
00156 if (peek_header(packed_form, len) != OKAY) {
00157 #ifdef DEBUG_CROMP_TRANSACTION
00158 LOG("failed to peek the header!");
00159 #endif
00160 return false;
00161 }
00162 packed_form.zap(0, 14 - 1);
00163 if (!req_id.unpack(packed_form)) return false;
00164 int array_len = len - 14 - req_id.packed_size();
00165
00166 #ifdef DEBUG_CROMP_TRANSACTION
00167 if (array_len > packed_form.length())
00168 continuable_error(static_class_name(), func,
00169 "data needed is insufficient! peek was wrong.");
00170 #endif
00171
00172 still_flat = packed_form.subarray(0, array_len - 1);
00173 packed_form.zap(0, array_len - 1);
00174 return true;
00175 }
00176
00177 #define WHACK_AND_GO { packed_form.zap(0, 0); continue; }
00178
00179 #define CHECK_LENGTH \
00180 if (packed_form.length() < necessary_length) { \
00181 \
00182 return true; \
00183 } \
00184 necessary_length++;
00185
00186 bool cromp_transaction::resynchronize(byte_array &packed_form)
00187 {
00188 FUNCDEF("resynchronize");
00189 while (true) {
00190 if (!packed_form.length()) {
00191
00192 LOG("roasted entire contents...");
00193
00194 return false;
00195 }
00196 if (packed_form[0] != 'c') WHACK_AND_GO;
00197 int necessary_length = 2;
00198 CHECK_LENGTH;
00199 if (packed_form[1] != 'r') WHACK_AND_GO;
00200 CHECK_LENGTH;
00201 if (packed_form[2] != 'o') WHACK_AND_GO;
00202 CHECK_LENGTH;
00203 if (packed_form[3] != 'm') WHACK_AND_GO;
00204 CHECK_LENGTH;
00205 if (packed_form[4] != 'p') WHACK_AND_GO;
00206 CHECK_LENGTH;
00207 if (packed_form[5] != '!') WHACK_AND_GO;
00208 for (int k = 6; k < 14; k++) {
00209 CHECK_LENGTH;
00210 if (!parser_bits::is_hexadecimal(packed_form[k]))
00211 WHACK_AND_GO;
00212 }
00213 #ifdef DEBUG_CROMP_TRANSACTION
00214 LOG("found header again...");
00215 #endif
00216 return true;
00217 }
00218 }
00219
00220 outcome cromp_transaction::peek_header(const byte_array &packed_form,
00221 int &length)
00222 {
00223 FUNCDEF("peek_header");
00224 length = 0;
00225 #ifdef DEBUG_CROMP_TRANSACTION
00226 LOG("checking for header");
00227 #endif
00228 if (packed_form.length() < 14) return WAY_TOO_SMALL;
00229 if ( (packed_form[0] != 'c') || (packed_form[1] != 'r')
00230 || (packed_form[2] != 'o') || (packed_form[3] != 'm')
00231 || (packed_form[4] != 'p') || (packed_form[5] != '!') )
00232 return GARBAGE;
00233 #ifdef DEBUG_CROMP_TRANSACTION
00234 LOG("obvious header bits look fine");
00235 #endif
00236
00237 istring len_string;
00238 for (int k = 6; k < 14; k++) {
00239 if (!parser_bits::is_hexadecimal(packed_form[k])) {
00240 #ifdef DEBUG_CROMP_TRANSACTION
00241 LOG("found corruption in hex bytes");
00242 #endif
00243 return GARBAGE;
00244 }
00245 len_string += char(packed_form[k]);
00246 }
00247 #ifdef DEBUG_CROMP_TRANSACTION
00248 LOG("length was unpacked okay");
00249 #endif
00250 u_int temp_len = (u_int)length;
00251 int items = sscanf(len_string.s(), "%08x", &temp_len);
00252 length = temp_len;
00253 if (!items) {
00254 #ifdef DEBUG_CROMP_TRANSACTION
00255 LOG(istring("couldn't parse the len_string of: ") + len_string);
00256 #endif
00257 return GARBAGE;
00258 }
00259
00260 #ifdef DEBUG_CROMP_TRANSACTION
00261 LOG(isprintf("length string is %s, len calc is %d and bytes "
00262 "given are %d", len_string.s(), length, packed_form.length()));
00263 #endif
00264 if (length > MAXIMUM_TRANSACTION) return ILLEGAL_LENGTH;
00265 if (length > packed_form.length()) return PARTIAL;
00266 return OKAY;
00267 }
00268
00269
00270 #endif //CROMP_TRANSACTION_IMPLEMENTATION_FILE
00271