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