00001 // $Id: arca_8c-example.html,v 1.2 2006/02/09 19:12:40 Daniel.May Exp $ 00002 // 00003 // FIX Adapted for STreaming (sm) (FAST Protocol (sm)) 00004 // 00005 // Copyright (c) 2005-2006, Pantor Engineering AB (http://www.pantor.com) 00006 // Copyright (c) 2005-2006, SpryWare LLC (http://www.spryware.com) 00007 // Copyright (c) 2005-2006, FIX Protocol Ltd (http://www.fixprotocol.org) 00008 // All Rights Reserved. 00009 // 00010 // This work is distributed under the W3C® Software License [1] in the 00011 // hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 00012 // implied warranty of MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS 00013 // FOR A PARTICULAR PURPOSE. 00014 // 00015 // [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 00016 // [FPL's Intellectual Property details] http://www.fixprotocol.org/ip 00017 // [FAST Protocol details] http://www.fixprotocol.org/fast 00018 // [FAST Protocol credits] http://fixprotocol.org/fastcredits 00019 00020 #include "arca.h" 00021 00022 static fast_codec_t* arca_codec = NULL; 00023 00024 static int cl_count = 0; 00025 static int cl_decode = 0; 00026 00028 00029 static insert_order_msg* swap_insert_order_msg (void* data) 00030 { 00031 insert_order_msg* msg = (insert_order_msg*) data; 00032 00033 swap16 (msg->size); 00034 swap32 (msg->time); 00035 swap32 (msg->seqno); 00036 swap32 (msg->order_ref); 00037 swap32 (msg->shares); 00038 swap32 (msg->price); 00039 00040 return msg; 00041 } 00042 00043 static delete_order_msg* swap_delete_order_msg (void* data) 00044 { 00045 delete_order_msg* msg = (delete_order_msg*) data; 00046 00047 swap16 (msg->size); 00048 swap32 (msg->time); 00049 swap32 (msg->seqno); 00050 swap32 (msg->order_ref); 00051 00052 return msg; 00053 } 00054 00055 static modify_order_msg* swap_modify_order_msg (void* data) 00056 { 00057 modify_order_msg* msg = (modify_order_msg*) data; 00058 00059 swap16 (msg->size); 00060 swap32 (msg->time); 00061 swap32 (msg->seqno); 00062 swap32 (msg->order_ref); 00063 swap32 (msg->shares); 00064 swap32 (msg->price); 00065 00066 return msg; 00067 } 00068 00069 static imbalance_msg* swap_imbalance_msg (void* data) 00070 { 00071 imbalance_msg* msg = (imbalance_msg*) data; 00072 00073 swap16 (msg->size); 00074 swap32 (msg->time); 00075 swap32 (msg->seqno); 00076 swap32 (msg->shares); 00077 swap32 (msg->total_imbal); 00078 swap32 (msg->market_imbal); 00079 swap32 (msg->price); 00080 swap32 (msg->auction_time); 00081 00082 return msg; 00083 } 00085 00086 static u32 decode_str (int tag, u8* data, int size) 00087 { 00088 fast_decode_str (arca_codec, tag, data, size); 00089 return 0; 00090 } 00091 00092 static u32 decode_u32 (int tag) 00093 { 00094 u32 temp; 00095 00096 fast_decode_u32 (arca_codec, tag, & temp); 00097 return temp; 00098 } 00099 00100 static i32 decode_i32 (int tag) 00101 { 00102 i32 temp; 00103 00104 fast_decode_i32 (arca_codec, tag, & temp); 00105 return temp; 00106 } 00107 00108 static inline void encode_i32 (u32 tag, i32 value) 00109 { 00110 fast_encode_u32 (arca_codec, tag, value); 00111 } 00112 00113 static inline void encode_u32 (u32 tag, u32 value) 00114 { 00115 fast_encode_u32 (arca_codec, tag, value); 00116 } 00117 00118 static inline void encode_str (int tag, u8* data, int size) 00119 { 00120 size = (int) strnlen ((char*) data, size); // remove trailing NULLs 00121 fast_encode_str (arca_codec, tag, data, size); 00122 } 00123 00125 00126 static inline void encode_new_msg (u32 tag) 00127 { 00128 fast_encode_new_msg (arca_codec, tag); 00129 } 00130 00131 static inline void encode_end_msg (u32 tag) 00132 { 00133 fast_encode_end_msg (arca_codec, tag); 00134 } 00135 00137 00138 static void decode_insert_order (int type) 00139 { 00140 insert_order_msg msg [1]; 00141 u32 secs, msecs; 00142 00143 memset (msg, 0, sizeof (*msg)); 00144 00145 msg->type = 'A'; 00146 msg->size = sizeof (insert_order_msg) - 4; 00147 00148 secs = decode_u32 (TSP_SECS); 00149 msecs = decode_u32 (TSP_MSECS); 00150 00151 msg->seqno = decode_u32 (SEQNO); 00152 msg->order_ref = decode_u32 (ORDER_REF); 00153 msg->shares = decode_u32 (SHARES); 00154 msg->price = decode_u32 (PRICE); 00155 msg->scale = decode_u32 (SCALE); 00156 msg->exch_code = decode_u32 (EXCH_CODE); 00157 msg->sys_code = decode_u32 (SYS_CODE); 00158 msg->buy_sell = decode_u32 (BUY_SELL); 00159 00160 decode_str (STOCK, STR_ARGS (msg->stock)); 00161 decode_str (QUOTE_ID, STR_ARGS (msg->quote_id)); 00162 00163 msg->time = secs * 1000 + msecs; 00164 00165 swap_insert_order_msg (msg); 00166 write_n (arca_codec->output->fd, msg, sizeof (*msg)); 00167 } 00168 00170 00171 static void decode_delete_order (int type) 00172 { 00173 delete_order_msg msg [1]; 00174 u32 secs, msecs; 00175 00176 memset (msg, 0, sizeof (*msg)); 00177 00178 msg->type = 'D'; 00179 msg->size = sizeof (delete_order_msg) - 4; 00180 00181 secs = decode_u32 (TSP_SECS); 00182 msecs = decode_u32 (TSP_MSECS); 00183 00184 msg->time = secs * 1000 + msecs; 00185 00186 msg->seqno = decode_u32 (SEQNO); 00187 msg->order_ref = decode_u32 (ORDER_REF); 00188 msg->exch_code = decode_u32 (EXCH_CODE); 00189 msg->sys_code = decode_u32 (SYS_CODE); 00190 msg->buy_sell = decode_u32 (BUY_SELL); 00191 00192 decode_str (STOCK, STR_ARGS (msg->stock)); 00193 decode_str (QUOTE_ID, STR_ARGS (msg->quote_id)); 00194 00195 swap_delete_order_msg (msg); 00196 write_n (arca_codec->output->fd, msg, sizeof (*msg)); 00197 } 00198 00200 00201 static void decode_modify_order (int type) 00202 { 00203 modify_order_msg msg [1]; 00204 u32 secs, msecs; 00205 00206 memset (msg, 0, sizeof (*msg)); 00207 00208 msg->type = 'M'; 00209 msg->size = sizeof (modify_order_msg) - 4; 00210 00211 secs = decode_u32 (TSP_SECS); 00212 msecs = decode_u32 (TSP_MSECS); 00213 00214 msg->time = secs * 1000 + msecs; 00215 00216 msg->seqno = decode_u32 (SEQNO); 00217 msg->order_ref = decode_u32 (ORDER_REF); 00218 msg->shares = decode_u32 (SHARES); 00219 msg->price = decode_u32 (PRICE); 00220 msg->scale = decode_u32 (SCALE); 00221 msg->exch_code = decode_u32 (EXCH_CODE); 00222 msg->sys_code = decode_u32 (SYS_CODE); 00223 msg->buy_sell = decode_u32 (BUY_SELL); 00224 00225 decode_str (STOCK, STR_ARGS (msg->stock)); 00226 decode_str (QUOTE_ID, STR_ARGS (msg->quote_id)); 00227 00228 swap_modify_order_msg (msg); 00229 write_n (arca_codec->output->fd, msg, sizeof (*msg)); 00230 } 00231 00233 00234 static void decode_imbalance (int type) 00235 { 00236 imbalance_msg msg [1]; 00237 u32 secs, msecs; 00238 00239 memset (msg, 0, sizeof (*msg)); 00240 00241 msg->type = 'I'; 00242 msg->size = sizeof (imbalance_msg) - 4; 00243 00244 secs = decode_u32 (TSP_SECS); 00245 msecs = decode_u32 (TSP_MSECS); 00246 00247 msg->time = secs * 1000 + msecs; 00248 00249 msg->seqno = decode_u32 (SEQNO); 00250 msg->shares = decode_u32 (SHARES); 00251 00252 msg->price = decode_u32 (PRICE); 00253 msg->scale = decode_u32 (SCALE); 00254 00255 msg->exch_code = decode_u32 (EXCH_CODE); 00256 msg->sys_code = decode_u32 (SYS_CODE); 00257 00258 decode_str (STOCK, STR_ARGS (msg->stock)); 00259 00260 msg->market_imbal = decode_i32 (MARKET_IMBAL); 00261 msg->total_imbal = decode_i32 (TOTAL_IMBAL); 00262 00263 msg->auction_type = decode_u32 (AUCT_TYPE); 00264 msg->auction_time = decode_u32 (AUCT_TIME); 00265 00266 swap_imbalance_msg (msg); 00267 write_n (arca_codec->output->fd, msg, sizeof (*msg)); 00268 } 00269 00271 00272 static int encode_insert_order (insert_order_msg* msg) 00273 { 00274 encode_new_msg (ARCA_BASE_TID); 00275 00276 encode_u32 (MSG_TYPE, msg->type); 00277 encode_u32 (TSP_SECS, msg->time / 1000); 00278 encode_u32 (TSP_MSECS, msg->time % 1000); 00279 00280 encode_u32 (SEQNO, msg->seqno); 00281 encode_u32 (ORDER_REF, msg->order_ref); 00282 encode_u32 (SHARES, msg->shares); 00283 encode_u32 (PRICE, msg->price); 00284 encode_u32 (SCALE, msg->scale); 00285 00286 encode_u32 (EXCH_CODE, msg->exch_code); 00287 encode_u32 (SYS_CODE, msg->sys_code); 00288 encode_u32 (BUY_SELL, msg->buy_sell); 00289 00290 encode_str (STOCK, STR_ARGS (msg->stock)); 00291 encode_str (QUOTE_ID, STR_ARGS (msg->quote_id)); 00292 00293 encode_end_msg (ARCA_BASE_TID); 00294 return 0; 00295 } 00296 00298 00299 static int encode_delete_order (delete_order_msg* msg) 00300 { 00301 encode_new_msg (ARCA_BASE_TID); 00302 00303 encode_u32 (MSG_TYPE, msg->type); 00304 encode_u32 (TSP_SECS, msg->time / 1000); 00305 encode_u32 (TSP_MSECS, msg->time % 1000); 00306 00307 encode_u32 (SEQNO, msg->seqno); 00308 encode_u32 (ORDER_REF, msg->order_ref); 00309 00310 encode_u32 (EXCH_CODE, msg->exch_code); 00311 encode_u32 (SYS_CODE, msg->sys_code); 00312 encode_u32 (BUY_SELL, msg->buy_sell); 00313 00314 encode_str (STOCK, STR_ARGS (msg->stock)); 00315 encode_str (QUOTE_ID, STR_ARGS (msg->quote_id)); 00316 00317 encode_end_msg (ARCA_BASE_TID); 00318 return 0; 00319 } 00320 00322 00323 static int encode_modify_order (modify_order_msg* msg) 00324 { 00325 encode_new_msg (ARCA_BASE_TID); 00326 00327 encode_u32 (MSG_TYPE, msg->type); 00328 encode_u32 (TSP_SECS, msg->time / 1000); 00329 encode_u32 (TSP_MSECS, msg->time % 1000); 00330 00331 encode_u32 (SEQNO, msg->seqno); 00332 encode_u32 (ORDER_REF, msg->order_ref); 00333 encode_u32 (SHARES, msg->shares); 00334 encode_u32 (PRICE, msg->price); 00335 encode_u32 (SCALE, msg->scale); 00336 00337 encode_u32 (EXCH_CODE, msg->exch_code); 00338 encode_u32 (SYS_CODE, msg->sys_code); 00339 encode_u32 (BUY_SELL, msg->buy_sell); 00340 00341 encode_str (STOCK, STR_ARGS (msg->stock)); 00342 encode_str (QUOTE_ID, STR_ARGS (msg->quote_id)); 00343 00344 encode_end_msg (ARCA_BASE_TID); 00345 return 0; 00346 } 00347 00349 00350 static int encode_imbalance (imbalance_msg* msg) 00351 { 00352 encode_new_msg (ARCA_BASE_TID); 00353 00354 encode_u32 (MSG_TYPE, msg->type); 00355 encode_u32 (TSP_SECS, msg->time / 1000); 00356 encode_u32 (TSP_MSECS, msg->time % 1000); 00357 00358 encode_u32 (SEQNO, msg->seqno); 00359 encode_u32 (SHARES, msg->shares); 00360 00361 encode_u32 (PRICE, msg->price); 00362 encode_u32 (SCALE, msg->scale); 00363 00364 encode_u32 (EXCH_CODE, msg->exch_code); 00365 encode_u32 (SYS_CODE, msg->sys_code); 00366 00367 encode_str (STOCK, STR_ARGS (msg->stock)); 00368 00369 encode_i32 (MARKET_IMBAL, msg->market_imbal); 00370 encode_i32 (TOTAL_IMBAL, msg->total_imbal); 00371 00372 encode_u32 (AUCT_TYPE, msg->auction_type); 00373 encode_u32 (AUCT_TIME, msg->auction_time); 00374 00375 encode_end_msg (ARCA_BASE_TID); 00376 return 0; 00377 } 00378 00380 00381 static int arca_decoder (void) 00382 { 00383 int count; 00384 00385 for (count = 1 ;; count ++) 00386 { 00387 u32 msg_type; 00388 00389 if (cl_count > 0 && count > cl_count) 00390 break; 00391 00392 if (fast_decode_new_msg (arca_codec, ARCA_BASE_TID) < 0) 00393 break; 00394 00395 msg_type = decode_u32 (MSG_TYPE); 00396 00397 switch (msg_type) 00398 { 00399 case 'A': 00400 decode_insert_order (msg_type); 00401 break; 00402 00403 case 'D': 00404 decode_delete_order (msg_type); 00405 break; 00406 00407 case 'M': 00408 decode_modify_order (msg_type); 00409 break; 00410 00411 case 'I': 00412 decode_imbalance (msg_type); 00413 break; 00414 00415 default: 00416 fprintf (stderr, "fatal: %02x unknown type\n", msg_type); 00417 exit (0); 00418 } 00419 00420 if (fast_decode_end_msg (arca_codec, ARCA_BASE_TID) < 0) 00421 break; 00422 } 00423 return 0; 00424 } 00425 00426 static int arca_encoder (void) 00427 { 00428 char data [128]; 00429 00430 int error = 0; 00431 int count; 00432 00433 for (count = 0 ; cl_count == 0 || count < cl_count ; count ++) 00434 { 00435 char* hdr = data; 00436 char* body = hdr + 4; // VC can't do arith on void* 00437 00438 int length; 00439 00440 // Read four bytes header 00441 if (read_n (arca_codec->input->fd, data, 4) < 0) 00442 return -1; 00443 00444 length = (hdr [0] << 8) | hdr [1]; 00445 00446 assert (length <= sizeof (data) - 4); 00447 00448 // Read the body part 00449 if (read_n (arca_codec->input->fd, body, length) < 0) 00450 { 00451 perror ("read_n: body part"); 00452 break; 00453 } 00454 00455 switch (data [2]) 00456 { 00457 case 'A': 00458 encode_insert_order (swap_insert_order_msg (data)); 00459 break; 00460 00461 case 'D': 00462 encode_delete_order (swap_delete_order_msg (data)); 00463 break; 00464 00465 case 'I': 00466 encode_imbalance (swap_imbalance_msg (data)); 00467 break; 00468 00469 case 'M': 00470 encode_modify_order (swap_modify_order_msg (data)); 00471 break; 00472 00473 default: 00474 fprintf (stderr, "fatal: unknown type='%c'\n", data [2]); 00475 abort (); 00476 } 00477 00478 if (error != 0) 00479 break; 00480 } 00481 return 0; 00482 } 00483 00485 00486 #define OPTS "A:c:DV?" 00487 00488 int main (int argc, char* argv []) 00489 { 00490 init_platform_io (); 00491 00492 arca_codec = fast_create_codec (); 00493 00494 assert (arca_codec != NULL); 00495 00496 for (;;) 00497 { 00498 int option = getopt (argc, argv, OPTS); 00499 00500 if (option == EOF) 00501 break; 00502 00503 switch (option) 00504 { 00505 case 'c': 00506 cl_count = atoi (optarg); 00507 break; 00508 00509 case 'D': 00510 cl_decode = 1; 00511 break; 00512 00513 case 'V': 00514 arca_codec->verbose ++; 00515 break; 00516 00517 case '?': 00518 fprintf (stderr, "encoder [-cDV] <infile >outfile\n"); 00519 exit (0); 00520 00521 default: 00522 fprintf (stderr, "error: '%c' unknown option\n", option); 00523 exit (1); 00524 } 00525 } 00526 00527 if (cl_decode) 00528 arca_decoder (); 00529 else 00530 arca_encoder (); 00531 00532 exit (0); 00533 }