00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00075 #include "fap.h"
00076 #include "helpers.h"
00077 #include "regs.h"
00078 #ifdef HAVE_CONFIG_H
00079 #include <config.h>
00080 #endif
00081
00082 #include <stdlib.h>
00083 #include <string.h>
00084 #include <regex.h>
00085 #include <ctype.h>
00086 #include <math.h>
00087 #include <stdio.h>
00088
00089
00091 #define PI 3.14159265
00093 #define DEG2RAD(x) (x/360*2*PI)
00095 #define RAD2DEG(x) (x*2*PI*360)
00096
00098 #define FEND 0xc0
00100 #define FESC 0xdb
00102 #define TFEND 0xdc
00104 #define TFESC 0xdd
00106 #define FRAME_MAXLEN 512
00107
00109 #define AX25_FRAME_UI 0x03
00111 #define AX25_PID_APRS 0xf0
00112
00113
00114
00115
00116 regex_t fapint_regex_header, fapint_regex_ax25call, fapint_regex_digicall, fapint_regex_digicallv6;
00117 regex_t fapint_regex_normalpos, fapint_regex_normalamb, fapint_regex_timestamp;
00118 regex_t fapint_regex_mice_dstcall, fapint_regex_mice_body, fapint_regex_mice_amb;
00119 regex_t fapint_regex_comment, fapint_regex_phgr, fapint_regex_phg, fapint_regex_rng, fapint_regex_altitude;
00120 regex_t fapint_regex_mes_dst, fapint_regex_mes_ack, fapint_regex_mes_nack;
00121 regex_t fapint_regex_wx1, fapint_regex_wx2, fapint_regex_wx3, fapint_regex_wx4, fapint_regex_wx5;
00122 regex_t fapint_regex_wx_r1, fapint_regex_wx_r24, fapint_regex_wx_rami;
00123 regex_t fapint_regex_wx_humi, fapint_regex_wx_pres, fapint_regex_wx_lumi, fapint_regex_wx_what;
00124 regex_t fapint_regex_wx_snow, fapint_regex_wx_rrc, fapint_regex_wx_any, fapint_regex_wx_soft;
00125 regex_t fapint_regex_nmea_chksum, fapint_regex_nmea_dst, fapint_regex_nmea_time, fapint_regex_nmea_date;
00126 regex_t fapint_regex_nmea_specou, fapint_regex_nmea_fix, fapint_regex_nmea_altitude, fapint_regex_nmea_flag, fapint_regex_nmea_coord;
00127 regex_t fapint_regex_telemetry, fapint_regex_peet_splitter, fapint_regex_kiss_callsign, fapint_regex_kiss_digi;
00128
00129
00130 regex_t fapint_regex_detect_comp, fapint_regex_detect_wx, fapint_regex_detect_telem, fapint_regex_detect_exp;
00131 regex_t fapint_regex_kiss_hdrbdy, fapint_regex_hdr_detail;
00132 regex_t fapint_regex_hopcount1, fapint_regex_hopcount2;
00133
00134
00135 short fapint_initialized = 0;
00136
00137
00138
00139 fap_packet_t* fap_parseaprs(char const* input, unsigned int const input_len, short const is_ax25)
00140 {
00141 fap_packet_t* result;
00142 int i, pos;
00143 unsigned int splitpos, body_len;
00144 char* body;
00145 char* tmp;
00146 char poschar, typechar;
00147
00148
00149 if ( !fapint_initialized )
00150 {
00151 return NULL;
00152 }
00153
00154
00155 result = fapint_create_packet();
00156
00157
00158 if ( input == NULL || input_len == 0 )
00159 {
00160 result->error_code = malloc(sizeof(fap_error_code_t));
00161 if ( result->error_code ) *result->error_code = fapPACKET_NO;
00162 return result;
00163 }
00164
00165
00166 result->orig_packet = malloc(input_len);
00167 result->orig_packet_len = input_len;
00168 memcpy(result->orig_packet, input, input_len);
00169
00170
00171 splitpos = 0;
00172 for ( i = 0; i < input_len; ++i )
00173 {
00174 if ( input[i] == 0 )
00175 {
00176 result->error_code = malloc(sizeof(fap_error_code_t));
00177 if ( result->error_code ) *result->error_code = fapPACKET_INVALID;
00178 return result;
00179 }
00180 if ( input[i] == ':' )
00181 {
00182 splitpos = i;
00183 break;
00184 }
00185 }
00186
00187 if ( splitpos == 0 || splitpos + 1 == input_len )
00188 {
00189 result->error_code = malloc(sizeof(fap_error_code_t));
00190 if ( result->error_code ) *result->error_code = fapPACKET_NOBODY;
00191 return result;
00192 }
00193
00194
00195 result->header = fapint_remove_part(input, input_len, splitpos, input_len, &body_len);
00196 result->body = fapint_remove_part(input, input_len, 0, splitpos+1, &result->body_len);
00197
00198
00199 if ( !fapint_parse_header(result, is_ax25) )
00200 {
00201 return result;
00202 }
00203
00204
00205 body_len = result->body_len;
00206 body = malloc(body_len + 1);
00207 memcpy(body, result->body, body_len);
00208 body[body_len] = 0;
00209
00210
00211 typechar = body[0];
00212
00213
00214 if ( (typechar == 0x27 || typechar == 0x60) &&
00215 body_len >= 9 )
00216 {
00217 result->type = malloc(sizeof(fap_packet_type_t));
00218 if ( !result->type ) return result;
00219 *result->type = fapLOCATION;
00220 fapint_parse_mice(result, body+1, body_len-1);
00221 }
00222
00223 else if ( typechar == '!' || typechar == '=' || typechar == '/' || typechar == '@' )
00224 {
00225
00226 result->messaging = malloc(sizeof(short));
00227 if ( !result->messaging ) return result;
00228 if ( typechar == '=' || typechar == '@' )
00229 {
00230 *result->messaging = 1;
00231 }
00232 else
00233 {
00234 *result->messaging = 0;
00235 }
00236
00237 if ( body_len >= 14 )
00238 {
00239 result->type = malloc(sizeof(fap_packet_type_t));
00240 if ( !result->type ) return result;
00241 *result->type = fapLOCATION;
00242
00243 i = 1;
00244 if ( typechar == '/' || typechar == '@' )
00245 {
00246
00247 result->timestamp = malloc(sizeof(time_t));
00248 if ( !result->timestamp ) return result;
00249 *result->timestamp = fapint_parse_timestamp(body+1);
00250 if ( result->timestamp == NULL )
00251 {
00252 result->error_code = malloc(sizeof(fap_error_code_t));
00253 if ( result->error_code ) *result->error_code = fapTIMESTAMP_INV_LOC;
00254 i = 0;
00255 }
00256 tmp = fapint_remove_part(body, body_len, 0, 8, &body_len);
00257 free(body);
00258 body = tmp;
00259 }
00260 else
00261 {
00262
00263 tmp = fapint_remove_part(body, body_len, 0, 1, &body_len);
00264 free(body);
00265 body = tmp;
00266 }
00267
00268
00269 if ( i )
00270 {
00271
00272 poschar = body[0];
00273
00274
00275 if ( poschar >= 48 && poschar <= 57 )
00276 {
00277
00278 if ( body_len >= 19 )
00279 {
00280 i = fapint_parse_normal(result, body);
00281
00282 if ( body_len > 19 && i && result->symbol_code != '_' )
00283 {
00284 fapint_parse_comment(result, body+19, body_len-19);
00285 }
00286 else if ( body_len > 19 && i )
00287 {
00288 fapint_parse_wx(result, body+19, body_len-19);
00289 }
00290 }
00291 }
00292 else if ( poschar == 47 || poschar == 92 || (poschar >= 65 && poschar <= 90) || (poschar >= 97 && poschar <= 106) )
00293 {
00294
00295 if ( body_len >= 13 )
00296 {
00297 i = fapint_parse_compressed(result, body);
00298
00299 if ( body_len > 13 && i && result->symbol_code != '_' )
00300 {
00301 fapint_parse_comment(result, body+13, body_len-13);
00302 }
00303 else if ( body_len > 13 && i )
00304 {
00305 fapint_parse_wx(result, body+13, body_len-13);
00306 }
00307 }
00308 else
00309 {
00310 result->error_code = malloc(sizeof(fap_error_code_t));
00311 if ( result->error_code ) *result->error_code = fapCOMP_SHORT;
00312 }
00313 }
00314 else if ( poschar == 33 )
00315 {
00316
00317 if ( result->type == NULL )
00318 {
00319 result->type = malloc(sizeof(fap_packet_type_t));
00320 if ( !result->type ) return result;
00321 }
00322 *result->type = fapWX;
00323 fapint_parse_wx_peet_logging(result, body+1);
00324 }
00325 else
00326 {
00327
00328 result->error_code = malloc(sizeof(fap_error_code_t));
00329 if ( result->error_code ) *result->error_code = fapPACKET_INVALID;
00330 }
00331 }
00332 }
00333 else
00334 {
00335 result->error_code = malloc(sizeof(fap_error_code_t));
00336 if ( result->error_code ) *result->error_code = fapPACKET_SHORT;
00337 }
00338 }
00339
00340 else if ( typechar == '$' )
00341 {
00342 if ( body_len > 3 && body[0] == '$' && body[1] == 'G' && body[2] == 'P' )
00343 {
00344 result->type = malloc(sizeof(fap_packet_type_t));
00345 if ( !result->type ) return result;
00346 *result->type = fapLOCATION;
00347 fapint_parse_nmea(result, body+1, body_len-1);
00348 }
00349 else if ( body_len > 5 && body[0] == '$' && body[1] == 'U' && body[2] == 'L' && body[3] == 'T' && body[4] == 'W' )
00350 {
00351 result->type = malloc(sizeof(fap_packet_type_t));
00352 if ( !result->type ) return result;
00353 *result->type = fapWX;
00354 fapint_parse_wx_peet_packet(result, body+5);
00355 }
00356 }
00357
00358 else if ( typechar == ';' )
00359 {
00360 if ( body_len >= 31 )
00361 {
00362 result->type = malloc(sizeof(fap_packet_type_t));
00363 if ( !result->type ) return result;
00364 *result->type = fapOBJECT;
00365 fapint_parse_object(result, body, body_len);
00366 }
00367 }
00368
00369 else if ( typechar == ')' )
00370 {
00371 if ( body_len >= 18 )
00372 {
00373 result->type = malloc(sizeof(fap_packet_type_t));
00374 if ( !result->type ) return result;
00375 *result->type = fapITEM;
00376 fapint_parse_item(result, body, body_len);
00377 }
00378 }
00379
00380 else if ( typechar == ':' )
00381 {
00382 if ( body_len >= 11 )
00383 {
00384
00385 result->type = malloc(sizeof(fap_packet_type_t));
00386 if ( !result->type ) return result;
00387 *result->type = fapMESSAGE;
00388 fapint_parse_message(result, body, body_len);
00389 }
00390 }
00391
00392 else if ( typechar == '<' )
00393 {
00394
00395 if ( body_len >= 2 )
00396 {
00397 result->type = malloc(sizeof(fap_packet_type_t));
00398 if ( !result->type ) return result;
00399 *result->type = fapCAPABILITIES;
00400 fapint_parse_capabilities(result, body+1, body_len-1);
00401 }
00402 }
00403
00404 else if ( typechar == '>' )
00405 {
00406
00407 if ( body_len >= 1 )
00408 {
00409 result->type = malloc(sizeof(fap_packet_type_t));
00410 if ( !result->type ) return result;
00411 *result->type = fapSTATUS;
00412 fapint_parse_status(result, body+1, body_len-1);
00413 }
00414 }
00415
00416 else if ( typechar == '_' )
00417 {
00418 if ( regexec(&fapint_regex_detect_wx, body, 0, NULL, 0) == 0 )
00419 {
00420 result->type = malloc(sizeof(fap_packet_type_t));
00421 if ( !result->type ) return result;
00422 *result->type = fapWX;
00423 fapint_parse_wx(result, body+9, body_len-9);
00424 }
00425 else
00426 {
00427 result->error_code = malloc(sizeof(fap_error_code_t));
00428 if ( result->error_code ) *result->error_code = fapWX_UNSUPP;
00429 }
00430 }
00431
00432 else if ( regexec(&fapint_regex_detect_telem, body, 0, NULL, 0) == 0 )
00433 {
00434 result->type = malloc(sizeof(fap_packet_type_t));
00435 if ( !result->type ) return result;
00436 *result->type = fapTELEMETRY;
00437 fapint_parse_telemetry(result, body+2);
00438 }
00439
00440 else if ( regexec(&fapint_regex_detect_exp, body, 0, NULL, 0) == 0 )
00441 {
00442 result->type = malloc(sizeof(fap_packet_type_t));
00443 if ( !result->type ) return result;
00444 *result->type = fapEXPERIMENTAL;
00445 result->error_code = malloc(sizeof(fap_error_code_t));
00446 if ( result->error_code ) *result->error_code = fapEXP_UNSUPP;
00447 }
00448
00449 else if ( typechar == '}' )
00450 {
00451
00452 }
00453
00454
00455 else
00456 {
00457 tmp = strchr(body, '!');
00458 if ( tmp != NULL && (pos = tmp-body) < 40 && pos+1 < body_len )
00459 {
00460 result->type = malloc(sizeof(fap_packet_type_t));
00461 if ( !result->type ) return result;
00462 *result->type = fapLOCATION;
00463 poschar = tmp[1];
00464
00465
00466 if ( poschar == 47 || poschar == 92 || (poschar >= 65 && poschar <= 90) || (poschar >= 97 && poschar <= 106) )
00467 {
00468
00469 if ( body_len >= pos + 1 + 13 )
00470 {
00471 i = fapint_parse_compressed(result, body+pos+1);
00472
00473 if ( body_len - (pos+1) > 13 && i && result->symbol_code != '_' )
00474 {
00475 fapint_parse_comment(result, body+pos+1+13, body_len-pos-1-13);
00476 }
00477 }
00478 }
00479 else if ( isdigit(poschar) )
00480 {
00481
00482 if ( body_len >= pos + 1 + 19 )
00483 {
00484 i = fapint_parse_normal(result, tmp+1);
00485
00486 if ( body_len - (pos+1) > 19 && i && result->symbol_code != '_' )
00487 {
00488 fapint_parse_comment(result, body+pos+1+19, body_len-pos-1-19);
00489 }
00490 }
00491 }
00492 }
00493 else
00494 {
00495
00496 result->error_code = malloc(sizeof(fap_error_code_t));
00497 if ( result->error_code ) *result->error_code = fapNO_APRS;
00498 }
00499 }
00500
00501
00502 free(body);
00503
00504 return result;
00505 }
00506
00507
00508
00509 void fap_explain_error(fap_error_code_t const error, char* output)
00510 {
00511
00512 if ( output == NULL )
00513 {
00514 return;
00515 }
00516
00517 switch (error)
00518 {
00519 case fapPACKET_NO:
00520 sprintf(output, "No packet given to parse");
00521 break;
00522 case fapPACKET_SHORT:
00523 sprintf(output, "Too short packet");
00524 break;
00525 case fapPACKET_NOBODY:
00526 sprintf(output, "No body in packet");
00527 break;
00528
00529 case fapSRCCALL_NOAX25:
00530 sprintf(output, "Source callsign is not a valid AX.25 call");
00531 break;
00532 case fapSRCCALL_BADCHARS:
00533 sprintf(output, "Source callsign contains bad characters");
00534 break;
00535
00536 case fapDSTPATH_TOOMANY:
00537 sprintf(output, "Too many destination path components to be AX.25");
00538 break;
00539 case fapDSTCALL_NONE:
00540 sprintf(output, "No destination field in packet");
00541 break;
00542 case fapDSTCALL_NOAX25:
00543 sprintf(output, "Destination callsign is not a valid AX.25 call");
00544 break;
00545
00546 case fapDIGICALL_NOAX25:
00547 sprintf(output, "Digipeater callsign is not a valid AX.25 call");
00548 break;
00549 case fapDIGICALL_BADCHARS:
00550 sprintf(output, "Digipeater callsign contains bad characters");
00551 break;
00552
00553 case fapTIMESTAMP_INV_LOC:
00554 sprintf(output, "Invalid timestamp in location");
00555 break;
00556 case fapTIMESTAMP_INV_OBJ:
00557 sprintf(output, "Invalid timestamp in object");
00558 break;
00559 case fapTIMESTAMP_INV_STA:
00560 sprintf(output, "Invalid timestamp in status");
00561 break;
00562 case fapTIMESTAMP_INV_GPGGA:
00563 sprintf(output, "Invalid timestamp in GPGGA sentence");
00564 break;
00565 case fapTIMESTAMP_INV_GPGLL:
00566 sprintf(output, "Invalid timestamp in GPGLL sentence");
00567 break;
00568
00569 case fapPACKET_INVALID:
00570 sprintf(output, "Invalid packet");
00571 break;
00572
00573 case fapNMEA_INV_CVAL:
00574 sprintf(output, "Invalid coordinate value in NMEA sentence");
00575 break;
00576 case fapNMEA_LARGE_EW:
00577 sprintf(output, "Too large value in NMEA sentence (east/west)");
00578 break;
00579 case fapNMEA_LARGE_NS:
00580 sprintf(output, "Too large value in NMEA sentence (north/south)");
00581 break;
00582 case fapNMEA_INV_SIGN:
00583 sprintf(output, "Invalid lat/long sign in NMEA sentence");
00584 break;
00585 case fapNMEA_INV_CKSUM:
00586 sprintf(output, "Invalid checksum in NMEA sentence");
00587 break;
00588
00589 case fapGPRMC_FEWFIELDS:
00590 sprintf(output, "Less than ten fields in GPRMC sentence");
00591 break;
00592 case fapGPRMC_NOFIX:
00593 sprintf(output, "No GPS fix in GPRMC sentence");
00594 break;
00595 case fapGPRMC_INV_TIME:
00596 sprintf(output, "Invalid timestamp in GPRMC sentence");
00597 break;
00598 case fapGPRMC_INV_DATE:
00599 sprintf(output, "Invalid date in GPRMC sentence");
00600 break;
00601 case fapGPRMC_DATE_OUT:
00602 sprintf(output, "GPRMC date does not fit in an Unix timestamp");
00603 break;
00604
00605 case fapGPGGA_FEWFIELDS:
00606 sprintf(output, "Less than 11 fields in GPGGA sentence");
00607 break;
00608 case fapGPGGA_NOFIX:
00609 sprintf(output, "No GPS fix in GPGGA sentence");
00610 break;
00611
00612 case fapGPGLL_FEWFIELDS:
00613 sprintf(output, "Less than 5 fields in GPGLL sentence");
00614 break;
00615 case fapGPGLL_NOFIX:
00616 sprintf(output, "No GPS fix in GPGLL sentence");
00617 break;
00618
00619 case fapNMEA_UNSUPP:
00620 sprintf(output, "Unsupported NMEA sentence type");
00621 break;
00622
00623 case fapOBJ_SHORT:
00624 sprintf(output, "Too short object");
00625 break;
00626 case fapOBJ_INV:
00627 sprintf(output, "Invalid object");
00628 break;
00629 case fapOBJ_DEC_ERR:
00630 sprintf(output, "Error in object location decoding");
00631 break;
00632
00633 case fapITEM_SHORT:
00634 sprintf(output, "Too short item");
00635 break;
00636 case fapITEM_INV:
00637 sprintf(output, "Invalid item");
00638 break;
00639 case fapITEM_DEC_ERR:
00640 sprintf(output, "Error in item location decoding");
00641 break;
00642
00643 case fapLOC_SHORT:
00644 sprintf(output, "Too short uncompressed location");
00645 break;
00646 case fapLOC_INV:
00647 sprintf(output, "Invalid uncompressed location");
00648 break;
00649 case fapLOC_LARGE:
00650 sprintf(output, "Degree value too large");
00651 break;
00652 case fapLOC_AMB_INV:
00653 sprintf(output, "Invalid position ambiguity");
00654 break;
00655
00656 case fapMICE_SHORT:
00657 sprintf(output, "Too short mic-e packet");
00658 break;
00659 case fapMICE_INV:
00660 sprintf(output, "Invalid characters in mic-e packet");
00661 break;
00662 case fapMICE_INV_INFO:
00663 sprintf(output, "Invalid characters in mic-e information field");
00664 break;
00665 case fapMICE_AMB_LARGE:
00666 sprintf(output, "Too much position ambiguity in mic-e packet");
00667 break;
00668 case fapMICE_AMB_INV:
00669 sprintf(output, "Invalid position ambiguity in mic-e packet");
00670 break;
00671 case fapMICE_AMB_ODD:
00672 sprintf(output, "Odd position ambiguity in mic-e packet");
00673 break;
00674
00675 case fapCOMP_INV:
00676 sprintf(output, "Invalid compressed packet");
00677 break;
00678 case fapCOMP_SHORT:
00679 sprintf(output, "Short compressed packet");
00680 break;
00681
00682 case fapMSG_INV:
00683 sprintf(output, "Invalid message packet");
00684 break;
00685
00686 case fapWX_UNSUPP:
00687 sprintf(output, "Unsupported weather format");
00688 break;
00689 case fapUSER_UNSUPP:
00690 sprintf(output, "Unsupported user format");
00691 break;
00692
00693 case fapDX_INV_SRC:
00694 sprintf(output, "Invalid DX spot source callsign");
00695 break;
00696 case fapDX_INF_FREQ:
00697 sprintf(output, "Invalid DX spot frequency");
00698 break;
00699 case fapDX_NO_DX:
00700 sprintf(output, "No DX spot callsign found");
00701 break;
00702
00703 case fapTLM_INV:
00704 sprintf(output, "Invalid telemetry packet");
00705 break;
00706 case fapTLM_LARGE:
00707 sprintf(output, "Too large telemetry value");
00708 break;
00709 case fapTLM_UNSUPP:
00710 sprintf(output, "Unsupported telemetry");
00711 break;
00712
00713 case fapEXP_UNSUPP:
00714 sprintf(output, "Unsupported experimental");
00715 break;
00716 case fapSYM_INV_TABLE:
00717 sprintf(output, "Invalid symbol table or overlay");
00718 break;
00719
00720 case fapNOT_IMPLEMENTED:
00721 sprintf(output, "Sorry, feature not implemented yet.");
00722 break;
00723 case fapNMEA_NOFIELDS:
00724 sprintf(output, "No fields in NMEA fields in NMEA packet.");
00725 break;
00726
00727 case fapNO_APRS:
00728 sprintf(output, "Not an APRS packet");
00729 break;
00730
00731 default:
00732 sprintf(output, "Default error message.");
00733 break;
00734 }
00735 }
00736
00737
00738
00739 void fap_mice_mbits_to_message(char const* bits, char* output)
00740 {
00741
00742 if ( bits == NULL || output == NULL )
00743 {
00744 return;
00745 }
00746
00747
00748 if ( strcmp(bits, "111") == 0 ) sprintf(output, "off duty");
00749 else if ( strcmp(bits, "222") == 0 ) sprintf(output, "custom 0");
00750 else if ( strcmp(bits, "110") == 0 ) sprintf(output, "en route");
00751 else if ( strcmp(bits, "220") == 0 ) sprintf(output, "custom 1");
00752 else if ( strcmp(bits, "101") == 0 ) sprintf(output, "in service");
00753 else if ( strcmp(bits, "202") == 0 ) sprintf(output, "custom 2");
00754 else if ( strcmp(bits, "100") == 0 ) sprintf(output, "returning");
00755 else if ( strcmp(bits, "200") == 0 ) sprintf(output, "custom 3");
00756 else if ( strcmp(bits, "011") == 0 ) sprintf(output, "committed");
00757 else if ( strcmp(bits, "022") == 0 ) sprintf(output, "custom 4");
00758 else if ( strcmp(bits, "010") == 0 ) sprintf(output, "special");
00759 else if ( strcmp(bits, "020") == 0 ) sprintf(output, "custom 5");
00760 else if ( strcmp(bits, "001") == 0 ) sprintf(output, "priority");
00761 else if ( strcmp(bits, "002") == 0 ) sprintf(output, "custom 6");
00762 else if ( strcmp(bits, "000") == 0 ) sprintf(output, "emergency");
00763 else sprintf(output, "unknown");
00764 }
00765
00766
00767
00768 double fap_distance(double lon0, double lat0, double lon1, double lat1)
00769 {
00770
00771 lon0 = DEG2RAD(lon0);
00772 lat0 = DEG2RAD(lat0);
00773 lon1 = DEG2RAD(lon1);
00774 lat1 = DEG2RAD(lat1);
00775
00776
00777
00778 double dlon = lon1 - lon0;
00779 double dlat = lat1 - lat0;
00780 double a = pow(sin(dlat/2),2) + cos(lat0) * cos(lat1) * pow(sin(dlon/2), 2);
00781 double c = 2 * atan2(sqrt(a), sqrt(1-a));
00782
00783 return c * 6366.71;
00784 }
00785
00786
00787
00788 double fap_direction(double lon0, double lat0, double lon1, double lat1)
00789 {
00790 double direction;
00791
00792
00793 lon0 = DEG2RAD(lon0);
00794 lat0 = DEG2RAD(lat0);
00795 lon1 = DEG2RAD(lon1);
00796 lat1 = DEG2RAD(lat1);
00797
00798
00799
00800 direction = atan2(sin(lon1-lon0)*cos(lat1), cos(lat0)*sin(lat1)-sin(lat0)*cos(lat1)*cos(lon1-lon0));
00801 if ( direction < 0 )
00802 {
00803
00804 direction += 2 * PI;
00805 }
00806
00807 return RAD2DEG(direction);
00808 }
00809
00810
00811
00812 int fap_count_digihops(fap_packet_t const* packet)
00813 {
00814 int i, len;
00815 unsigned int hopcount = 0, n, N;
00816 short wasdigied;
00817 char* element;
00818 char* call_ssid;
00819
00820 unsigned int const matchcount = 3;
00821 regmatch_t matches[matchcount];
00822
00823
00824
00825 if ( !fapint_initialized || packet == NULL || packet->path == NULL )
00826 {
00827 return -1;
00828 }
00829
00830
00831 for ( i = 0; i < packet->path_len; ++i )
00832 {
00833 wasdigied = 0;
00834
00835
00836 if ( regexec(&fapint_regex_hopcount1, packet->path[i], matchcount, (regmatch_t*)&matches, 0) == 0 )
00837 {
00838 wasdigied = 1;
00839
00840
00841 len = matches[1].rm_eo - matches[1].rm_so;
00842 element = malloc(len+1);
00843 if ( !element ) return -1;
00844 memcpy(element, packet->path[i]+matches[1].rm_so, len);
00845 element[len] = 0;
00846
00847
00848 call_ssid = fap_check_ax25_call(element, 1);
00849 free(element);
00850 }
00851 else
00852 {
00853 call_ssid = fap_check_ax25_call(packet->path[i], 1);
00854 }
00855
00856
00857 if ( call_ssid == NULL )
00858 {
00859 return -1;
00860 }
00861
00862
00863 if ( regexec(&fapint_regex_hopcount2, call_ssid, matchcount, (regmatch_t*)&matches, 0) == 0 )
00864 {
00865
00866 n = call_ssid[matches[1].rm_so] - 48;
00867 N = call_ssid[matches[2].rm_so] - 48;
00868
00869
00870 if ( (i = n - N) >= 0 )
00871 {
00872 hopcount += i;
00873 }
00874 }
00875 else
00876 {
00877
00878 if ( wasdigied )
00879 {
00880 hopcount++;
00881 }
00882 }
00883
00884
00885 free(call_ssid);
00886 }
00887
00888 return hopcount;
00889 }
00890
00891
00892
00893 char* fap_check_ax25_call(char const* input, short const add_ssid0)
00894 {
00895 unsigned int const matchcount = 3;
00896 regmatch_t matches[matchcount];
00897
00898 int ssid = 0, len;
00899 char call[7], ssid_str[4];
00900
00901 char* result = NULL;
00902 char buf[10];
00903
00904
00905
00906 if ( !fapint_initialized )
00907 {
00908 return NULL;
00909 }
00910
00911
00912 if ( !input || !strlen(input) )
00913 {
00914 return NULL;
00915 }
00916
00917
00918 if ( regexec(&fapint_regex_ax25call, input, matchcount, (regmatch_t*)&matches, 0) == 0 )
00919 {
00920
00921 memset(call, 0, 7);
00922 len = matches[1].rm_eo - matches[1].rm_so;
00923 memcpy(call, input+matches[1].rm_so, len);
00924
00925
00926 memset(ssid_str, 0, 4);
00927 len = matches[2].rm_eo - matches[2].rm_so;
00928 memcpy(ssid_str, input+matches[2].rm_so, len);
00929
00930
00931 if ( len )
00932 {
00933 ssid = atoi(ssid_str);
00934 ssid = 0 - ssid;
00935 if ( ssid > 15 )
00936 {
00937 return NULL;
00938 }
00939 }
00940
00941
00942 memset(buf, 0, 10);
00943 if ( !add_ssid0 && ssid == 0 )
00944 {
00945 sprintf(buf, "%s", call);
00946 }
00947 else
00948 {
00949 sprintf(buf, "%s-%d", call, ssid);
00950 }
00951
00952 result = malloc( strlen(buf)+1 );
00953 if ( !result ) return NULL;
00954 strcpy(result, buf);
00955 }
00956
00957
00958 return result;
00959 }
00960
00961
00962
00963 int fap_kiss_to_tnc2(char const* kissframe, unsigned int kissframe_len,
00964 char* tnc2frame, unsigned int* tnc2frame_len, unsigned int* tnc_id)
00965 {
00966 char input[FRAME_MAXLEN];
00967 unsigned int input_len = 0;
00968
00969 char output[2*FRAME_MAXLEN];
00970 unsigned int output_len = 0;
00971
00972 int i = 0, j = 0, escape_mode = 0;
00973
00974
00975 if ( !kissframe || !kissframe_len || !tnc2frame || !tnc2frame_len || !tnc_id )
00976 {
00977 return 0;
00978 }
00979
00980
00981 if ( kissframe_len >= FRAME_MAXLEN )
00982 {
00983 sprintf(output, "Too long KISS frame.");
00984 output_len = strlen(output)+1;
00985 if ( output_len > *tnc2frame_len ) output_len = *tnc2frame_len;
00986 memcpy(tnc2frame, output, output_len);
00987 *tnc2frame_len = output_len;
00988 return 0;
00989 }
00990
00991
00992 if ( kissframe_len > 0 && (kissframe[0] & 0xff) == FEND )
00993 {
00994 kissframe += 1;
00995 kissframe_len -= 1;
00996 }
00997
00998
00999 for ( i = 0; i < kissframe_len; ++i )
01000 {
01001 if ( (kissframe[i] & 0xff) == FEND )
01002 {
01003 kissframe_len = i;
01004 }
01005 }
01006
01007
01008 if ( kissframe_len > 0 )
01009 {
01010 *tnc_id = kissframe[0];
01011 kissframe += 1;
01012 kissframe_len -= 1;
01013 }
01014
01015
01016 j = 0;
01017 for ( i = 0; i < kissframe_len; ++i )
01018 {
01019 if ( (kissframe[i] & 0xff) == FESC )
01020 {
01021 escape_mode = 1;
01022 continue;
01023 }
01024
01025 if ( escape_mode )
01026 {
01027 if ( (kissframe[i] & 0xff) == TFEND )
01028 {
01029 input[j] = FEND;
01030 }
01031 else if ( (kissframe[i] & 0xff) == TFESC )
01032 {
01033 input[j] = FESC;
01034 }
01035 escape_mode = 0;
01036 ++j;
01037 continue;
01038 }
01039
01040 input[j] = kissframe[i];
01041 ++j;
01042 }
01043 input_len = j;
01044
01045
01046 if ( input_len < 16 )
01047 {
01048 sprintf(output, "Too short KISS frame (%d bytes after unstuffing).", input_len);
01049 output_len = strlen(output)+1;
01050 if ( output_len > *tnc2frame_len ) output_len = *tnc2frame_len;
01051 memcpy(tnc2frame, output, output_len);
01052 *tnc2frame_len = output_len;
01053 return 0;
01054 }
01055
01056
01057 return fap_ax25_to_tnc2(input, input_len, tnc2frame, tnc2frame_len);
01058 }
01059
01060
01061
01062 int fap_ax25_to_tnc2(char const* ax25frame, unsigned int ax25frame_len,
01063 char* tnc2frame, unsigned int* tnc2frame_len)
01064 {
01065 int i, j, retval = 1;
01066 char *checked_call, *dst_callsign = NULL;
01067 int part_no, header_len, ssid, digi_count;
01068 char tmp_callsign[10];
01069 char charri;
01070
01071 char output[2*FRAME_MAXLEN];
01072 unsigned int output_len = 0;
01073
01074
01075 if ( !ax25frame || !ax25frame_len || !tnc2frame || !tnc2frame_len )
01076 {
01077 return 0;
01078 }
01079
01080
01081 if ( ax25frame_len >= FRAME_MAXLEN )
01082 {
01083 sprintf(output, "Too long AX.25 frame.");
01084 output_len = strlen(output)+1;
01085 if ( output_len > *tnc2frame_len ) output_len = *tnc2frame_len;
01086 memcpy(tnc2frame, output, output_len);
01087 *tnc2frame_len = output_len;
01088 return 0;
01089 }
01090 if ( ax25frame_len < 16 )
01091 {
01092 sprintf(output, "Too short AX.25 frame (%d bytes).", ax25frame_len);
01093 output_len = strlen(output)+1;
01094 if ( output_len > *tnc2frame_len ) output_len = *tnc2frame_len;
01095 memcpy(tnc2frame, output, output_len);
01096 *tnc2frame_len = output_len;
01097 return 0;
01098 }
01099
01100
01101 part_no = 0;
01102 header_len = 0;
01103 memset(tmp_callsign, 0, 10);
01104 digi_count = 0;
01105 j = 0;
01106 for ( i = 0; i < ax25frame_len; ++i )
01107 {
01108 charri = ax25frame[i];
01109
01110 if ( part_no == 0 )
01111 {
01112
01113 header_len++;
01114
01115
01116 if ( charri & 1 )
01117 {
01118
01119 if ( header_len < 14 || header_len % 7 != 0 )
01120 {
01121 sprintf(output, "Invalid header lenght (%d).", header_len);
01122 output_len = strlen(output)+1;
01123 retval = 0;
01124 break;
01125 }
01126
01127
01128 part_no = 1;
01129 }
01130
01131
01132 if ( header_len && header_len % 7 == 0 )
01133 {
01134
01135 ssid = (charri >> 1) & 0xf;
01136 if ( ssid != 0 )
01137 {
01138 sprintf(tmp_callsign+6, "-%d", ssid);
01139 }
01140
01141 checked_call = fapint_check_kiss_callsign(tmp_callsign);
01142 if ( !checked_call )
01143 {
01144 sprintf(output, "Invalid callsign in header (%s).", tmp_callsign);
01145 output_len = strlen(output)+1;
01146 retval = 0;
01147 break;
01148 }
01149
01150 if ( header_len == 7 )
01151 {
01152
01153 dst_callsign = checked_call;
01154 }
01155 else if ( header_len == 14 )
01156 {
01157
01158 sprintf(output, "%s>%s", checked_call, dst_callsign);
01159 output_len = strlen(checked_call) + 1 + strlen(dst_callsign);
01160 free(dst_callsign);
01161 free(checked_call);
01162 }
01163 else if ( header_len > 14 )
01164 {
01165
01166 sprintf(output+output_len, "%s", checked_call);
01167 output_len += strlen(checked_call);
01168 free(checked_call);
01169
01170 if ( charri & 0x80 )
01171 {
01172 output[output_len] = '*';
01173 output_len++;
01174 }
01175 digi_count++;
01176 }
01177 else
01178 {
01179 sprintf(output, "Internal error.");
01180 output_len = strlen(output)+1;
01181 retval = 0;
01182 break;
01183 }
01184
01185 if ( part_no == 0 )
01186 {
01187
01188 if ( digi_count >= 8 )
01189 {
01190 sprintf(output, "Too many digis.");
01191 output_len = strlen(output)+1;
01192 retval = 0;
01193 break;
01194 }
01195 output[output_len] = ',';
01196 output_len++;
01197 }
01198 else
01199 {
01200
01201 output[output_len] = ':';
01202 output_len++;
01203 }
01204 j = 0;
01205 memset(tmp_callsign, 0, 10);
01206 continue;
01207 }
01208
01209
01210 tmp_callsign[j] = (charri & 0xff) >> 1;
01211 ++j;
01212 }
01213 else if ( part_no == 1 )
01214 {
01215
01216 if ( (charri & 0xff) != AX25_FRAME_UI )
01217 {
01218 retval = 0;
01219 break;
01220 }
01221 part_no = 2;
01222 }
01223 else if ( part_no == 2 )
01224 {
01225
01226 if ( (charri & 0xff) != AX25_PID_APRS )
01227 {
01228 retval = 0;
01229 break;
01230 }
01231 part_no = 3;
01232 }
01233 else
01234 {
01235 output[output_len] = charri;
01236 output_len++;
01237 }
01238 }
01239
01240
01241 if ( output_len > *tnc2frame_len ) output_len = *tnc2frame_len;
01242 memcpy(tnc2frame, output, output_len);
01243 *tnc2frame_len = output_len;
01244
01245 return retval;
01246 }
01247
01248
01249
01250 int fap_tnc2_to_kiss(char const* tnc2frame, unsigned int tnc2frame_len, unsigned int const tnc_id,
01251 char* kissframe, unsigned int* kissframe_len)
01252 {
01253 char ax25frame[2*FRAME_MAXLEN];
01254 unsigned int ax25frame_len;
01255 int i;
01256
01257
01258 ax25frame_len = 2*FRAME_MAXLEN-2;
01259 memset(ax25frame, 0, 2);
01260
01261
01262 if ( !fap_tnc2_to_ax25(tnc2frame, tnc2frame_len, ax25frame+2, &ax25frame_len) )
01263 {
01264 strcpy(kissframe, ax25frame);
01265 *kissframe_len = strlen(kissframe);
01266 return 0;
01267 }
01268 ax25frame_len += 2;
01269
01270
01271 if ( *kissframe_len <= ax25frame_len )
01272 {
01273 return 0;
01274 }
01275
01276
01277 *kissframe_len = 2;
01278 for ( i = 2; i < ax25frame_len; ++i )
01279 {
01280 if ( (ax25frame[i] & 0xff) == FEND || (ax25frame[i] & 0xff) == FESC )
01281 {
01282 kissframe[*kissframe_len] = FESC;
01283 (*kissframe_len)++;
01284 if ( (ax25frame[i] & 0xff) == FEND )
01285 {
01286 kissframe[*kissframe_len] = TFEND;
01287 }
01288 else
01289 {
01290 kissframe[*kissframe_len] = TFESC;
01291 }
01292 (*kissframe_len)++;
01293 }
01294 else
01295 {
01296 kissframe[*kissframe_len] = ax25frame[i];
01297 (*kissframe_len)++;
01298 }
01299 }
01300
01301
01302 kissframe[0] = FEND;
01303 kissframe[1] = tnc_id;
01304 kissframe[*kissframe_len] = FEND;
01305 (*kissframe_len)++;
01306
01307 return 1;
01308 }
01309
01310
01311
01312 int fap_tnc2_to_ax25(char const* tnc2frame, unsigned int tnc2frame_len,
01313 char* ax25frame, unsigned int* ax25frame_len)
01314 {
01315 char input[FRAME_MAXLEN];
01316
01317 char output[2*FRAME_MAXLEN];
01318 unsigned int output_len = 0;
01319
01320 char *header = NULL, *digipeaters = NULL, *body = NULL;
01321 unsigned int digi_count, body_len;
01322
01323 char sender[6], sender_ssid[4], receiver[6], receiver_ssid[4];
01324 int sender_ssid_num = 0, receiver_ssid_num = 0;
01325
01326 char digicall[6], digicall_ssid[4], hbit;
01327 int digicall_ssid_num = 0;
01328
01329 int retval = 1, len, i;
01330 char* tmp_str;
01331
01332 unsigned int const matchcount = 6;
01333 regmatch_t matches[matchcount];
01334
01335
01336
01337 if ( !tnc2frame || !tnc2frame_len || tnc2frame_len >= FRAME_MAXLEN || !ax25frame || !ax25frame_len )
01338 {
01339 return 0;
01340 }
01341
01342
01343 memset(input, 0, FRAME_MAXLEN);
01344 memcpy(input, tnc2frame, tnc2frame_len );
01345
01346
01347 if ( regexec(&fapint_regex_kiss_hdrbdy, input, matchcount, (regmatch_t*)&matches, 0) == 0 )
01348 {
01349 len = matches[1].rm_eo - matches[1].rm_so;
01350 header = malloc(len+1);
01351 if ( !header ) return 0;
01352 memcpy(header, input+matches[1].rm_so, len);
01353 header[len] = 0;
01354
01355 body_len = matches[2].rm_eo - matches[2].rm_so;
01356 body = malloc(body_len);
01357 if ( !body )
01358 {
01359 free(header);
01360 return 0;
01361 }
01362 memcpy(body, input+matches[2].rm_so, body_len);
01363 }
01364 else
01365 {
01366 sprintf(output, "Failed to separate header and body of TNC-2 packet.");
01367 output_len = strlen(output)+1;
01368 if ( output_len > *ax25frame_len ) output_len = *ax25frame_len;
01369 strcpy(ax25frame, output);
01370 *ax25frame_len = output_len;
01371 return 0;
01372 }
01373
01374
01375 if ( regexec(&fapint_regex_hdr_detail, header, matchcount, (regmatch_t*)&matches, 0) == 0 )
01376 {
01377 len = matches[1].rm_eo - matches[1].rm_so;
01378 memset(sender, ' ', 6);
01379 memcpy(sender, header+matches[1].rm_so, len);
01380
01381 len = matches[2].rm_eo - matches[2].rm_so;
01382 memset(sender_ssid, 0, 4);
01383 if ( len )
01384 {
01385 memcpy(sender_ssid, header+matches[2].rm_so, len);
01386 }
01387
01388 len = matches[3].rm_eo - matches[3].rm_so;
01389 memset(receiver, ' ', 6);
01390 memcpy(receiver, header+matches[3].rm_so, len);
01391
01392 len = matches[4].rm_eo - matches[4].rm_so;
01393 memset(receiver_ssid, 0, 4);
01394 if ( len )
01395 {
01396 memcpy(receiver_ssid, header+matches[4].rm_so, len);
01397 }
01398
01399 len = matches[5].rm_eo - matches[5].rm_so;
01400 if ( len )
01401 {
01402 digipeaters = malloc(len+5);
01403 if ( !digipeaters )
01404 {
01405 free(header);
01406 free(body);
01407 return 0;
01408 }
01409 memcpy(digipeaters, header+matches[5].rm_so, len);
01410 digipeaters[len] = 0;
01411 }
01412 }
01413 else
01414 {
01415 free(header);
01416 free(body);
01417 return 0;
01418 }
01419 free(header);
01420
01421
01422 while ( 1 )
01423 {
01424
01425 if ( sender_ssid[0] == '-' )
01426 {
01427 sender_ssid_num = 0 - atoi(sender_ssid);
01428 if ( sender_ssid_num > 15 )
01429 {
01430 retval = 0;
01431 break;
01432 }
01433 }
01434 if ( receiver_ssid[0] == '-' )
01435 {
01436 receiver_ssid_num = 0 - atoi(receiver_ssid);
01437 if ( receiver_ssid_num > 15 )
01438 {
01439 retval = 0;
01440 break;
01441 }
01442 }
01443
01444
01445 for ( i = 0; i < 6; ++i )
01446 {
01447 output[output_len] = receiver[i] << 1;
01448 output_len++;
01449 }
01450 output[output_len] = 0xe0 | (receiver_ssid_num << 1);
01451 output_len++;
01452 for ( i = 0; i < 6; ++i )
01453 {
01454 output[output_len] = sender[i] << 1;
01455 output_len++;
01456 }
01457 if ( digipeaters )
01458 {
01459 output[output_len] = 0x60 | (sender_ssid_num << 1);
01460 }
01461 else
01462 {
01463 output[output_len] = 0x61 | (sender_ssid_num << 1);
01464 }
01465 output_len++;
01466
01467
01468 if ( digipeaters )
01469 {
01470
01471 tmp_str = strtok(digipeaters+1, ",");
01472 digi_count = 0;
01473 while ( tmp_str != NULL )
01474 {
01475
01476 if ( regexec(&fapint_regex_kiss_digi, tmp_str, matchcount, (regmatch_t*)&matches, 0) == 0 )
01477 {
01478
01479 len = matches[1].rm_eo - matches[1].rm_so;
01480 memset(digicall, ' ', 6);
01481 memcpy(digicall, tmp_str+matches[1].rm_so, len);
01482
01483
01484 digicall_ssid_num = 0;
01485 len = matches[2].rm_eo - matches[2].rm_so;
01486 if ( len )
01487 {
01488 memset(digicall_ssid, 0, 4);
01489 memcpy(digicall_ssid, tmp_str+matches[2].rm_so, len);
01490
01491 digicall_ssid_num = 0 - atoi(digicall_ssid);
01492 if ( digicall_ssid_num > 15 )
01493 {
01494 retval = 0;
01495 break;
01496 }
01497 }
01498
01499
01500 hbit = 0x00;
01501 if ( tmp_str[matches[3].rm_so] == '*' )
01502 {
01503 hbit = 0x80;
01504 }
01505
01506
01507 tmp_str = strtok(NULL, ",");
01508
01509
01510 for ( i = 0; i < 6; ++i )
01511 {
01512 output[output_len] = digicall[i] << 1;
01513 output_len++;
01514 }
01515
01516 if ( tmp_str )
01517 {
01518
01519 output[output_len] = 0x60 | (digicall_ssid_num << 1);
01520 }
01521 else
01522 {
01523
01524 output[output_len] = 0x61 | (digicall_ssid_num << 1);
01525 }
01526 output_len++;
01527 }
01528 else
01529 {
01530
01531 retval = 0;
01532 break;
01533 }
01534 }
01535 }
01536
01537
01538 break;
01539 }
01540 if ( digipeaters ) free(digipeaters);
01541
01542
01543
01544 output[output_len] = AX25_FRAME_UI;
01545 output_len++;
01546 output[output_len] = AX25_PID_APRS;
01547 output_len++;
01548
01549
01550 memcpy(output+output_len, body, body_len);
01551 output_len += body_len;
01552 free(body);
01553
01554
01555 if ( !retval )
01556 {
01557 return 0;
01558 }
01559
01560
01561 if ( output_len > *ax25frame_len ) output_len = *ax25frame_len;
01562 memcpy(ax25frame, output, output_len);
01563 *ax25frame_len = output_len;
01564 return 1;
01565 }
01566
01567
01568
01569 void fap_init()
01570 {
01571 if ( !fapint_initialized )
01572 {
01573
01574 regcomp(&fapint_regex_header, "^([A-Z0-9\\-]{1,9})>(.*)$", REG_EXTENDED);
01575 regcomp(&fapint_regex_ax25call, "^([A-Z0-9]{1,6})(-[0-9]{1,2}|())$", REG_EXTENDED);
01576 regcomp(&fapint_regex_digicall, "^([a-zA-Z0-9-]{1,9})([*]?)$", REG_EXTENDED);
01577 regcomp(&fapint_regex_digicallv6, "^([0-9A-F]{32})$", REG_EXTENDED|REG_NOSUB);
01578
01579 regcomp(&fapint_regex_normalpos, "^([0-9]{2})([0-7 ][0-9 ]\\.[0-9 ]{2})([NnSs])(.)([0-9]{3})([0-7 ][0-9 ]\\.[0-9 ]{2})([EeWw])(.)", REG_EXTENDED);
01580 regcomp(&fapint_regex_normalamb, "^([0-9]{0,4})( {0,4})$", REG_EXTENDED);
01581 regcomp(&fapint_regex_timestamp, "^([0-9]{2})([0-9]{2})([0-9]{2})([zh\\/])", REG_EXTENDED);
01582
01583 regcomp(&fapint_regex_mice_dstcall, "^[0-9A-LP-Z]{3}[0-9LP-Z]{3}$", REG_EXTENDED|REG_NOSUB);
01584 regcomp(&fapint_regex_mice_body, "^[\\/\\\\A-Z0-9]", REG_EXTENDED|REG_NOSUB);
01585 regcomp(&fapint_regex_mice_amb, "^([0-9]+)(_*)$", REG_EXTENDED);
01586
01587 regcomp(&fapint_regex_comment, "^([0-9\\. ]{3})\\/([0-9\\. ]{3})", REG_EXTENDED|REG_NOSUB);
01588 regcomp(&fapint_regex_phgr, "^PHG([0-9].[0-9]{2}[1-9A-Z])\\/", REG_EXTENDED|REG_NOSUB);
01589 regcomp(&fapint_regex_phg, "^PHG([0-9].[0-9]{2})", REG_EXTENDED|REG_NOSUB);
01590 regcomp(&fapint_regex_rng, "^RNG([0-9]{4})", REG_EXTENDED|REG_NOSUB);
01591 regcomp(&fapint_regex_altitude, "\\/A=(-[0-9]{5}|[0-9]{6})", REG_EXTENDED);
01592
01593 regcomp(&fapint_regex_mes_dst, "^:([A-Za-z0-9_ -]{9}):", REG_EXTENDED);
01594 regcomp(&fapint_regex_mes_ack, "^ack([A-Za-z0-9}]{1,5}) *$", REG_EXTENDED);
01595 regcomp(&fapint_regex_mes_nack, "^rej([A-Za-z0-9}]{1,5}) *$", REG_EXTENDED);
01596
01597 regcomp(&fapint_regex_wx1, "^_{0,1}([0-9 \\.\\-]{3})\\/([0-9 \\.]{3})g([0-9 \\.]+)t(-{0,1}[0-9 \\.]+)", REG_EXTENDED);
01598 regcomp(&fapint_regex_wx2, "^_{0,1}c([0-9 \\.\\-]{3})s([0-9 \\.]{3})g([0-9 \\.]+)t(-{0,1}[0-9 \\.]+)", REG_EXTENDED);
01599 regcomp(&fapint_regex_wx3, "^_{0,1}([0-9 \\.\\-]{3})\\/([0-9 \\.]{3})t(-{0,1}[0-9 \\.]+)", REG_EXTENDED);
01600 regcomp(&fapint_regex_wx4, "^_{0,1}([0-9 \\.\\-]{3})\\/([0-9 \\.]{3})g([0-9 \\.]+)", REG_EXTENDED);
01601 regcomp(&fapint_regex_wx5, "^g([0-9]+)t(-?[0-9 \\.]{1,3})", REG_EXTENDED);
01602
01603 regcomp(&fapint_regex_wx_r1, "r([0-9]{1,3})", REG_EXTENDED);
01604 regcomp(&fapint_regex_wx_r24, "p([0-9]{1,3})", REG_EXTENDED);
01605 regcomp(&fapint_regex_wx_rami, "P([0-9]{1,3})", REG_EXTENDED);
01606
01607 regcomp(&fapint_regex_wx_humi, "h([0-9]{1,3})", REG_EXTENDED);
01608 regcomp(&fapint_regex_wx_pres, "b([0-9]{4,5})", REG_EXTENDED);
01609 regcomp(&fapint_regex_wx_lumi, "([lL])([0-9]{1,3})", REG_EXTENDED);
01610 regcomp(&fapint_regex_wx_what, "v([\\-\\+]{0,1}[0-9]+)", REG_EXTENDED);
01611
01612 regcomp(&fapint_regex_wx_snow, "s([0-9]+)", REG_EXTENDED);
01613 regcomp(&fapint_regex_wx_rrc, "#([0-9]+)", REG_EXTENDED);
01614 regcomp(&fapint_regex_wx_any, "^([rPphblLs#][\\. ]{1,5})+", REG_EXTENDED);
01615 regcomp(&fapint_regex_wx_soft, "^[a-zA-Z0-9\\-\\_]{3,5}$", REG_EXTENDED|REG_NOSUB);
01616
01617 regcomp(&fapint_regex_nmea_chksum, "^(.+)\\*([0-9A-F]{2})$", REG_EXTENDED);
01618 regcomp(&fapint_regex_nmea_dst, "^(GPS|SPC)([A-Z0-9]{2,3})", REG_EXTENDED);
01619 regcomp(&fapint_regex_nmea_time, "^[:space:]*([0-9]{2})([0-9]{2})([0-9]{2})(()|\\.[0-9]+)[:space:]*$", REG_EXTENDED);
01620 regcomp(&fapint_regex_nmea_date, "^[:space:]*([0-9]{2})([0-9]{2})([0-9]{2})[:space:]*$", REG_EXTENDED);
01621
01622 regcomp(&fapint_regex_nmea_specou, "^[:space:]*([0-9]+(()|\\.[0-9]+))[:space:]*$", REG_EXTENDED);
01623 regcomp(&fapint_regex_nmea_fix, "^[:space:]*([0-9]+)[:space:]*$", REG_EXTENDED);
01624 regcomp(&fapint_regex_nmea_altitude, "^(-?[0-9]+(()|\\.[0-9]+))$", REG_EXTENDED);
01625 regcomp(&fapint_regex_nmea_flag, "^[:space:]*([NSEWnsew])[:space:]*$", REG_EXTENDED);
01626 regcomp(&fapint_regex_nmea_coord, "^[:space:]*([0-9]{1,3})([0-5][0-9]\\.([0-9]+))[:space:]*$", REG_EXTENDED);
01627
01628 regcomp(&fapint_regex_telemetry, "^([0-9]+),(-?)([0-9]{1,6}|[0-9]+\\.[0-9]+|\\.[0-9]+)?,(-?)([0-9]{1,6}|[0-9]+\\.[0-9]+|\\.[0-9]+)?,(-?)([0-9]{1,6}|[0-9]+\\.[0-9]+|\\.[0-9]+)?,(-?)([0-9]{1,6}|[0-9]+\\.[0-9]+|\\.[0-9]+)?,(-?)([0-9]{1,6}|[0-9]+\\.[0-9]+|\\.[0-9]+)?,([01]{0,8})", REG_EXTENDED);
01629 regcomp(&fapint_regex_peet_splitter, "^([0-9a-f]{4}|----)", REG_EXTENDED|REG_ICASE);
01630 regcomp(&fapint_regex_kiss_callsign, "^([A-Z0-9]+) *(-[0-9]+)?$", REG_EXTENDED);
01631
01632 regcomp(&fapint_regex_detect_comp, "^[\\/\\\\A-Za-j]$", REG_EXTENDED|REG_NOSUB);
01633 regcomp(&fapint_regex_detect_wx, "^_([0-9]{8})c[- .0-9]{1,3}s[- .0-9]{1,3}", REG_EXTENDED|REG_NOSUB);
01634 regcomp(&fapint_regex_detect_telem, "^T#(.*?),(.*)$", REG_EXTENDED|REG_NOSUB);
01635 regcomp(&fapint_regex_detect_exp, "^\\{\\{", REG_EXTENDED|REG_NOSUB);
01636
01637 regcomp(&fapint_regex_kiss_hdrbdy, "^([A-Z0-9,*>-]+):(.+)$", REG_EXTENDED);
01638 regcomp(&fapint_regex_hdr_detail, "^([A-Z0-9]{1,6})(-[0-9]{1,2})?>([A-Z0-9]{1,6})(-[0-9]{1,2})?(,.*)?$", REG_EXTENDED);
01639 regcomp(&fapint_regex_kiss_digi, "^([A-Z0-9]{1,6})(-[0-9]{1,2})?(\\*)?$", REG_EXTENDED);
01640
01641 regcomp(&fapint_regex_hopcount1, "^([A-Z0-9-]+)\\*$", REG_EXTENDED);
01642 regcomp(&fapint_regex_hopcount2, "^WIDE([1-7])-([0-7])$", REG_EXTENDED);
01643
01644
01645
01646 fapint_initialized = 1;
01647 }
01648 }
01649
01650
01651
01652 void fap_cleanup()
01653 {
01654 if ( fapint_initialized )
01655 {
01656
01657 regfree(&fapint_regex_header);
01658 regfree(&fapint_regex_ax25call);
01659 regfree(&fapint_regex_digicall);
01660 regfree(&fapint_regex_digicallv6);
01661
01662 regfree(&fapint_regex_normalpos);
01663 regfree(&fapint_regex_normalamb);
01664 regfree(&fapint_regex_timestamp);
01665
01666 regfree(&fapint_regex_mice_dstcall);
01667 regfree(&fapint_regex_mice_body);
01668 regfree(&fapint_regex_mice_amb);
01669
01670 regfree(&fapint_regex_comment);
01671 regfree(&fapint_regex_phgr);
01672 regfree(&fapint_regex_phg);
01673 regfree(&fapint_regex_rng);
01674 regfree(&fapint_regex_altitude);
01675
01676 regfree(&fapint_regex_mes_dst);
01677 regfree(&fapint_regex_mes_ack);
01678 regfree(&fapint_regex_mes_nack);
01679
01680 regfree(&fapint_regex_wx1);
01681 regfree(&fapint_regex_wx2);
01682 regfree(&fapint_regex_wx3);
01683 regfree(&fapint_regex_wx4);
01684 regfree(&fapint_regex_wx5);
01685
01686 regfree(&fapint_regex_wx_r1);
01687 regfree(&fapint_regex_wx_r24);
01688 regfree(&fapint_regex_wx_rami);
01689
01690 regfree(&fapint_regex_wx_humi);
01691 regfree(&fapint_regex_wx_pres);
01692 regfree(&fapint_regex_wx_lumi);
01693 regfree(&fapint_regex_wx_what);
01694
01695 regfree(&fapint_regex_wx_snow);
01696 regfree(&fapint_regex_wx_rrc);
01697 regfree(&fapint_regex_wx_any);
01698 regfree(&fapint_regex_wx_soft);
01699
01700 regfree(&fapint_regex_nmea_chksum);
01701 regfree(&fapint_regex_nmea_dst);
01702 regfree(&fapint_regex_nmea_time);
01703 regfree(&fapint_regex_nmea_date);
01704
01705 regfree(&fapint_regex_nmea_specou);
01706 regfree(&fapint_regex_nmea_fix);
01707 regfree(&fapint_regex_nmea_altitude);
01708 regfree(&fapint_regex_nmea_flag);
01709 regfree(&fapint_regex_nmea_coord);
01710
01711 regfree(&fapint_regex_telemetry);
01712 regfree(&fapint_regex_peet_splitter);
01713 regfree(&fapint_regex_kiss_callsign);
01714
01715 regfree(&fapint_regex_detect_comp);
01716 regfree(&fapint_regex_detect_wx);
01717 regfree(&fapint_regex_detect_telem);
01718 regfree(&fapint_regex_detect_exp);
01719
01720 regfree(&fapint_regex_kiss_hdrbdy);
01721 regfree(&fapint_regex_hdr_detail);
01722 regfree(&fapint_regex_kiss_digi);
01723
01724 regfree(&fapint_regex_hopcount1);
01725 regfree(&fapint_regex_hopcount2);
01726
01727
01728 fapint_initialized = 0;
01729 }
01730 }
01731
01732
01733
01734 void fap_free(fap_packet_t* packet)
01735 {
01736 unsigned int i;
01737
01738 if ( packet == NULL )
01739 {
01740 return;
01741 }
01742
01743 if ( packet->error_code ) { free(packet->error_code); }
01744 if ( packet->type ) { free(packet->type); }
01745
01746 if ( packet->orig_packet ) { free(packet->orig_packet); }
01747
01748 if ( packet->header ) { free(packet->header); }
01749 if ( packet->body ) { free(packet->body); }
01750 if ( packet->src_callsign ) { free(packet->src_callsign); }
01751 if ( packet->dst_callsign ) { free(packet->dst_callsign); }
01752 for ( i = 0; i < packet->path_len; ++i )
01753 {
01754 if ( packet->path[i] ) { free(packet->path[i]); }
01755 }
01756 if ( packet->path ) { free(packet->path); }
01757
01758 if ( packet->latitude ) { free(packet->latitude); }
01759 if ( packet->longitude ) { free(packet->longitude); }
01760 if ( packet->format ) { free(packet->format); }
01761 if ( packet->pos_resolution ) { free(packet->pos_resolution); }
01762 if ( packet->pos_ambiguity ) { free(packet->pos_ambiguity); }
01763
01764 if ( packet->altitude ) { free(packet->altitude); }
01765 if ( packet->course ) { free(packet->course); }
01766 if ( packet->speed ) { free(packet->speed); }
01767
01768 if ( packet->messaging ) { free(packet->messaging); }
01769 if ( packet->destination ) { free(packet->destination); }
01770 if ( packet->message ) { free(packet->message); }
01771 if ( packet->message_ack ) { free(packet->message_ack); }
01772 if ( packet->message_nack ) { free(packet->message_nack); }
01773 if ( packet->message_id ) { free(packet->message_id); }
01774 if ( packet->comment ) { free(packet->comment); }
01775
01776 if ( packet->object_or_item_name ) { free(packet->object_or_item_name); }
01777 if ( packet->alive ) { free(packet->alive); }
01778
01779 if ( packet->gps_fix_status ) { free(packet->gps_fix_status); }
01780 if ( packet->radio_range ) { free(packet->radio_range); }
01781 if ( packet->phg ) { free(packet->phg); }
01782 if ( packet->timestamp ) { free(packet->timestamp); }
01783 if ( packet->nmea_checksum_ok ) { free(packet->nmea_checksum_ok); }
01784
01785 if ( packet->wx_report )
01786 {
01787 if ( packet->wx_report->wind_gust ) { free(packet->wx_report->wind_gust); }
01788 if ( packet->wx_report->wind_dir ) { free(packet->wx_report->wind_dir); }
01789 if ( packet->wx_report->wind_speed ) { free(packet->wx_report->wind_speed); }
01790
01791 if ( packet->wx_report->temp ) { free(packet->wx_report->temp); }
01792 if ( packet->wx_report->temp_in ) { free(packet->wx_report->temp_in); }
01793
01794 if ( packet->wx_report->rain_1h ) { free(packet->wx_report->rain_1h); }
01795 if ( packet->wx_report->rain_24h ) { free(packet->wx_report->rain_24h); }
01796 if ( packet->wx_report->rain_midnight ) { free(packet->wx_report->rain_midnight); }
01797
01798 if ( packet->wx_report->humidity ) { free(packet->wx_report->humidity); }
01799 if ( packet->wx_report->humidity_in ) { free(packet->wx_report->humidity_in); }
01800
01801 if ( packet->wx_report->pressure ) { free(packet->wx_report->pressure); }
01802 if ( packet->wx_report->luminosity ) { free(packet->wx_report->luminosity); }
01803
01804 if ( packet->wx_report->snow_24h ) { free(packet->wx_report->snow_24h); }
01805
01806 if ( packet->wx_report->soft ) { free(packet->wx_report->soft); }
01807
01808 free(packet->wx_report);
01809 }
01810
01811 if ( packet->telemetry ) { free(packet->telemetry); }
01812
01813 if ( packet->messagebits ) { free(packet->messagebits); }
01814 if ( packet->status ) { free(packet->status); }
01815 for ( i = 0; i < packet->capabilities_len*2; i += 2 )
01816 {
01817 if ( packet->capabilities[i] ) { free(packet->capabilities[i]); }
01818 if ( packet->capabilities[i+1] ) { free(packet->capabilities[i+1]); }
01819 }
01820 if ( packet->capabilities ) { free(packet->capabilities); }
01821
01822 free(packet);
01823 }