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 char* fap_explain_error(fap_error_code_t const error)
00510 {
00511 switch (error)
00512 {
00513 case fapPACKET_NO:
00514 return "No packet given to parse";
00515 case fapPACKET_SHORT:
00516 return "Too short packet";
00517 case fapPACKET_NOBODY:
00518 return "No body in packet";
00519
00520 case fapSRCCALL_NOAX25:
00521 return "Source callsign is not a valid AX.25 call";
00522 case fapSRCCALL_BADCHARS:
00523 return "Source callsign contains bad characters";
00524
00525 case fapDSTPATH_TOOMANY:
00526 return "Too many destination path components to be AX.25";
00527 case fapDSTCALL_NONE:
00528 return "No destination field in packet";
00529 case fapDSTCALL_NOAX25:
00530 return "Destination callsign is not a valid AX.25 call";
00531
00532 case fapDIGICALL_NOAX25:
00533 return "Digipeater callsign is not a valid AX.25 call";
00534 case fapDIGICALL_BADCHARS:
00535 return "Digipeater callsign contains bad characters";
00536
00537 case fapTIMESTAMP_INV_LOC:
00538 return "Invalid timestamp in location";
00539 case fapTIMESTAMP_INV_OBJ:
00540 return "Invalid timestamp in object";
00541 case fapTIMESTAMP_INV_STA:
00542 return "Invalid timestamp in status";
00543 case fapTIMESTAMP_INV_GPGGA:
00544 return "Invalid timestamp in GPGGA sentence";
00545 case fapTIMESTAMP_INV_GPGLL:
00546 return "Invalid timestamp in GPGLL sentence";
00547
00548 case fapPACKET_INVALID:
00549 return "Invalid packet";
00550
00551 case fapNMEA_INV_CVAL:
00552 return "Invalid coordinate value in NMEA sentence";
00553 case fapNMEA_LARGE_EW:
00554 return "Too large value in NMEA sentence (east/west)";
00555 case fapNMEA_LARGE_NS:
00556 return "Too large value in NMEA sentence (north/south)";
00557 case fapNMEA_INV_SIGN:
00558 return "Invalid lat/long sign in NMEA sentence";
00559 case fapNMEA_INV_CKSUM:
00560 return "Invalid checksum in NMEA sentence";
00561
00562 case fapGPRMC_FEWFIELDS:
00563 return "Less than ten fields in GPRMC sentence";
00564 case fapGPRMC_NOFIX:
00565 return "No GPS fix in GPRMC sentence";
00566 case fapGPRMC_INV_TIME:
00567 return "Invalid timestamp in GPRMC sentence";
00568 case fapGPRMC_INV_DATE:
00569 return "Invalid date in GPRMC sentence";
00570 case fapGPRMC_DATE_OUT:
00571 return "GPRMC date does not fit in an Unix timestamp";
00572
00573 case fapGPGGA_FEWFIELDS:
00574 return "Less than 11 fields in GPGGA sentence";
00575 case fapGPGGA_NOFIX:
00576 return "No GPS fix in GPGGA sentence";
00577
00578 case fapGPGLL_FEWFIELDS:
00579 return "Less than 5 fields in GPGLL sentence";
00580 case fapGPGLL_NOFIX:
00581 return "No GPS fix in GPGLL sentence";
00582
00583 case fapNMEA_UNSUPP:
00584 return "Unsupported NMEA sentence type";
00585
00586 case fapOBJ_SHORT:
00587 return "Too short object";
00588 case fapOBJ_INV:
00589 return "Invalid object";
00590 case fapOBJ_DEC_ERR:
00591 return "Error in object location decoding";
00592
00593 case fapITEM_SHORT:
00594 return "Too short item";
00595 case fapITEM_INV:
00596 return "Invalid item";
00597 case fapITEM_DEC_ERR:
00598 return "Error in item location decoding";
00599
00600 case fapLOC_SHORT:
00601 return "Too short uncompressed location";
00602 case fapLOC_INV:
00603 return "Invalid uncompressed location";
00604 case fapLOC_LARGE:
00605 return "Degree value too large";
00606 case fapLOC_AMB_INV:
00607 return "Invalid position ambiguity";
00608
00609 case fapMICE_SHORT:
00610 return "Too short mic-e packet";
00611 case fapMICE_INV:
00612 return "Invalid characters in mic-e packet";
00613 case fapMICE_INV_INFO:
00614 return "Invalid characters in mic-e information field";
00615 case fapMICE_AMB_LARGE:
00616 return "Too much position ambiguity in mic-e packet";
00617 case fapMICE_AMB_INV:
00618 return "Invalid position ambiguity in mic-e packet";
00619 case fapMICE_AMB_ODD:
00620 return "Odd position ambiguity in mic-e packet";
00621
00622 case fapCOMP_INV:
00623 return "Invalid compressed packet";
00624 case fapCOMP_SHORT:
00625 return "Short compressed packet";
00626
00627 case fapMSG_INV:
00628 return "Invalid message packet";
00629
00630 case fapWX_UNSUPP:
00631 return "Unsupported weather format";
00632 case fapUSER_UNSUPP:
00633 return "Unsupported user format";
00634
00635 case fapDX_INV_SRC:
00636 return "Invalid DX spot source callsign";
00637 case fapDX_INF_FREQ:
00638 return "Invalid DX spot frequency";
00639 case fapDX_NO_DX:
00640 return "No DX spot callsign found";
00641
00642 case fapTLM_INV:
00643 return "Invalid telemetry packet";
00644 case fapTLM_LARGE:
00645 return "Too large telemetry value";
00646 case fapTLM_UNSUPP:
00647 return "Unsupported telemetry";
00648
00649 case fapEXP_UNSUPP:
00650 return "Unsupported experimental";
00651 case fapSYM_INV_TABLE:
00652 return "Invalid symbol table or overlay";
00653
00654 case fapNOT_IMPLEMENTED:
00655 return "Sorry, feature not implemented yet.";
00656 case fapNMEA_NOFIELDS:
00657 return "No fields in NMEA fields in NMEA packet.";
00658
00659 case fapNO_APRS:
00660 return "Not an APRS packet";
00661 }
00662
00663 return "This message never appears.";
00664 }
00665
00666
00667
00668 char* fap_mice_mbits_to_message(char* bits)
00669 {
00670 if ( strcmp(bits, "111") == 0 ) return "off duty";
00671 if ( strcmp(bits, "222") == 0 ) return "custom 0";
00672 if ( strcmp(bits, "110") == 0 ) return "en route";
00673 if ( strcmp(bits, "220") == 0 ) return "custom 1";
00674 if ( strcmp(bits, "101") == 0 ) return "in service";
00675 if ( strcmp(bits, "202") == 0 ) return "custom 2";
00676 if ( strcmp(bits, "100") == 0 ) return "returning";
00677 if ( strcmp(bits, "200") == 0 ) return "custom 3";
00678 if ( strcmp(bits, "011") == 0 ) return "committed";
00679 if ( strcmp(bits, "022") == 0 ) return "custom 4";
00680 if ( strcmp(bits, "010") == 0 ) return "special";
00681 if ( strcmp(bits, "020") == 0 ) return "custom 5";
00682 if ( strcmp(bits, "001") == 0 ) return "priority";
00683 if ( strcmp(bits, "002") == 0 ) return "custom 6";
00684 if ( strcmp(bits, "000") == 0 ) return "emergency";
00685
00686 return NULL;
00687 }
00688
00689
00690
00691 double fap_distance(double lon0, double lat0, double lon1, double lat1)
00692 {
00693
00694 lon0 = DEG2RAD(lon0);
00695 lat0 = DEG2RAD(lat0);
00696 lon1 = DEG2RAD(lon1);
00697 lat1 = DEG2RAD(lat1);
00698
00699
00700
00701 double dlon = lon1 - lon0;
00702 double dlat = lat1 - lat0;
00703 double a = pow(sin(dlat/2),2) + cos(lat0) * cos(lat1) * pow(sin(dlon/2), 2);
00704 double c = 2 * atan2(sqrt(a), sqrt(1-a));
00705
00706 return c * 6366.71;
00707 }
00708
00709
00710
00711 double fap_direction(double lon0, double lat0, double lon1, double lat1)
00712 {
00713 double direction;
00714
00715
00716 lon0 = DEG2RAD(lon0);
00717 lat0 = DEG2RAD(lat0);
00718 lon1 = DEG2RAD(lon1);
00719 lat1 = DEG2RAD(lat1);
00720
00721
00722
00723 direction = atan2(sin(lon1-lon0)*cos(lat1), cos(lat0)*sin(lat1)-sin(lat0)*cos(lat1)*cos(lon1-lon0));
00724 if ( direction < 0 )
00725 {
00726
00727 direction += 2 * PI;
00728 }
00729
00730 return RAD2DEG(direction);
00731 }
00732
00733
00734
00735 int fap_count_digihops(fap_packet_t const* packet)
00736 {
00737 int i, len;
00738 unsigned int hopcount = 0, n, N;
00739 short wasdigied;
00740 char* element;
00741 char* call_ssid;
00742
00743 unsigned int const matchcount = 3;
00744 regmatch_t matches[matchcount];
00745
00746
00747
00748 if ( !fapint_initialized || packet == NULL || packet->path == NULL )
00749 {
00750 return -1;
00751 }
00752
00753
00754 for ( i = 0; i < packet->path_len; ++i )
00755 {
00756 wasdigied = 0;
00757
00758
00759 if ( regexec(&fapint_regex_hopcount1, packet->path[i], matchcount, (regmatch_t*)&matches, 0) == 0 )
00760 {
00761 wasdigied = 1;
00762
00763
00764 len = matches[1].rm_eo - matches[1].rm_so;
00765 element = malloc(len+1);
00766 if ( !element ) return -1;
00767 memcpy(element, packet->path[i]+matches[1].rm_so, len);
00768 element[len] = 0;
00769
00770
00771 call_ssid = fap_check_ax25_call(element, 1);
00772 free(element);
00773 }
00774 else
00775 {
00776 call_ssid = fap_check_ax25_call(packet->path[i], 1);
00777 }
00778
00779
00780 if ( call_ssid == NULL )
00781 {
00782 return -1;
00783 }
00784
00785
00786 if ( regexec(&fapint_regex_hopcount2, call_ssid, matchcount, (regmatch_t*)&matches, 0) == 0 )
00787 {
00788
00789 n = call_ssid[matches[1].rm_so] - 48;
00790 N = call_ssid[matches[2].rm_so] - 48;
00791
00792
00793 if ( (i = n - N) >= 0 )
00794 {
00795 hopcount += i;
00796 }
00797 }
00798 else
00799 {
00800
00801 if ( wasdigied )
00802 {
00803 hopcount++;
00804 }
00805 }
00806
00807
00808 free(call_ssid);
00809 }
00810
00811 return hopcount;
00812 }
00813
00814
00815
00816 char* fap_check_ax25_call(char const* input, short const add_ssid0)
00817 {
00818 unsigned int const matchcount = 3;
00819 regmatch_t matches[matchcount];
00820
00821 int ssid = 0, len;
00822 char call[7], ssid_str[4];
00823
00824 char* result = NULL;
00825 char buf[10];
00826
00827
00828
00829 if ( !fapint_initialized )
00830 {
00831 return NULL;
00832 }
00833
00834
00835 if ( !input || !strlen(input) )
00836 {
00837 return NULL;
00838 }
00839
00840
00841 if ( regexec(&fapint_regex_ax25call, input, matchcount, (regmatch_t*)&matches, 0) == 0 )
00842 {
00843
00844 memset(call, 0, 7);
00845 len = matches[1].rm_eo - matches[1].rm_so;
00846 memcpy(call, input+matches[1].rm_so, len);
00847
00848
00849 memset(ssid_str, 0, 4);
00850 len = matches[2].rm_eo - matches[2].rm_so;
00851 memcpy(ssid_str, input+matches[2].rm_so, len);
00852
00853
00854 if ( len )
00855 {
00856 ssid = atoi(ssid_str);
00857 ssid = 0 - ssid;
00858 if ( ssid > 15 )
00859 {
00860 return NULL;
00861 }
00862 }
00863
00864
00865 memset(buf, 0, 10);
00866 if ( !add_ssid0 && ssid == 0 )
00867 {
00868 sprintf(buf, "%s", call);
00869 }
00870 else
00871 {
00872 sprintf(buf, "%s-%d", call, ssid);
00873 }
00874
00875 result = malloc( strlen(buf)+1 );
00876 if ( !result ) return NULL;
00877 strcpy(result, buf);
00878 }
00879
00880
00881 return result;
00882 }
00883
00884
00885
00886 int fap_kiss_to_tnc2(char const* kissframe, unsigned int kissframe_len,
00887 char* tnc2frame, unsigned int* tnc2frame_len, unsigned int* tnc_id)
00888 {
00889 char input[FRAME_MAXLEN];
00890 unsigned int input_len = 0;
00891
00892 char output[2*FRAME_MAXLEN];
00893 unsigned int output_len = 0;
00894
00895 int i = 0, j = 0, escape_mode = 0;
00896
00897
00898 if ( !kissframe || !kissframe_len || !tnc2frame || !tnc2frame_len || !tnc_id )
00899 {
00900 return 0;
00901 }
00902
00903
00904 if ( kissframe_len >= FRAME_MAXLEN )
00905 {
00906 sprintf(output, "Too long KISS frame.");
00907 output_len = strlen(output)+1;
00908 if ( output_len > *tnc2frame_len ) output_len = *tnc2frame_len;
00909 memcpy(tnc2frame, output, output_len);
00910 *tnc2frame_len = output_len;
00911 return 0;
00912 }
00913
00914
00915 if ( kissframe_len > 0 && (kissframe[0] & 0xff) == FEND )
00916 {
00917 kissframe += 1;
00918 kissframe_len -= 1;
00919 }
00920
00921
00922 for ( i = 0; i < kissframe_len; ++i )
00923 {
00924 if ( (kissframe[i] & 0xff) == FEND )
00925 {
00926 kissframe_len = i;
00927 }
00928 }
00929
00930
00931 if ( kissframe_len > 0 )
00932 {
00933 *tnc_id = kissframe[0];
00934 kissframe += 1;
00935 kissframe_len -= 1;
00936 }
00937
00938
00939 j = 0;
00940 for ( i = 0; i < kissframe_len; ++i )
00941 {
00942 if ( (kissframe[i] & 0xff) == FESC )
00943 {
00944 escape_mode = 1;
00945 continue;
00946 }
00947
00948 if ( escape_mode )
00949 {
00950 if ( (kissframe[i] & 0xff) == TFEND )
00951 {
00952 input[j] = FEND;
00953 }
00954 else if ( (kissframe[i] & 0xff) == TFESC )
00955 {
00956 input[j] = FESC;
00957 }
00958 escape_mode = 0;
00959 ++j;
00960 continue;
00961 }
00962
00963 input[j] = kissframe[i];
00964 ++j;
00965 }
00966 input_len = j;
00967
00968
00969 if ( input_len < 16 )
00970 {
00971 sprintf(output, "Too short KISS frame (%d bytes after unstuffing).", input_len);
00972 output_len = strlen(output)+1;
00973 if ( output_len > *tnc2frame_len ) output_len = *tnc2frame_len;
00974 memcpy(tnc2frame, output, output_len);
00975 *tnc2frame_len = output_len;
00976 return 0;
00977 }
00978
00979
00980 return fap_ax25_to_tnc2(input, input_len, tnc2frame, tnc2frame_len);
00981 }
00982
00983
00984
00985 int fap_ax25_to_tnc2(char const* ax25frame, unsigned int ax25frame_len,
00986 char* tnc2frame, unsigned int* tnc2frame_len)
00987 {
00988 int i, j, retval = 1;
00989 char *checked_call, *dst_callsign = NULL;
00990 int part_no, header_len, ssid, digi_count;
00991 char tmp_callsign[10];
00992 char charri;
00993
00994 char output[2*FRAME_MAXLEN];
00995 unsigned int output_len = 0;
00996
00997
00998 if ( !ax25frame || !ax25frame_len || !tnc2frame || !tnc2frame_len )
00999 {
01000 return 0;
01001 }
01002
01003
01004 if ( ax25frame_len >= FRAME_MAXLEN )
01005 {
01006 sprintf(output, "Too long AX.25 frame.");
01007 output_len = strlen(output)+1;
01008 if ( output_len > *tnc2frame_len ) output_len = *tnc2frame_len;
01009 memcpy(tnc2frame, output, output_len);
01010 *tnc2frame_len = output_len;
01011 return 0;
01012 }
01013 if ( ax25frame_len < 16 )
01014 {
01015 sprintf(output, "Too short AX.25 frame (%d bytes).", ax25frame_len);
01016 output_len = strlen(output)+1;
01017 if ( output_len > *tnc2frame_len ) output_len = *tnc2frame_len;
01018 memcpy(tnc2frame, output, output_len);
01019 *tnc2frame_len = output_len;
01020 return 0;
01021 }
01022
01023
01024 part_no = 0;
01025 header_len = 0;
01026 memset(tmp_callsign, 0, 10);
01027 digi_count = 0;
01028 j = 0;
01029 for ( i = 0; i < ax25frame_len; ++i )
01030 {
01031 charri = ax25frame[i];
01032
01033 if ( part_no == 0 )
01034 {
01035
01036 header_len++;
01037
01038
01039 if ( charri & 1 )
01040 {
01041
01042 if ( header_len < 14 || header_len % 7 != 0 )
01043 {
01044 sprintf(output, "Invalid header lenght (%d).", header_len);
01045 output_len = strlen(output)+1;
01046 retval = 0;
01047 break;
01048 }
01049
01050
01051 part_no = 1;
01052 }
01053
01054
01055 if ( header_len && header_len % 7 == 0 )
01056 {
01057
01058 ssid = (charri >> 1) & 0xf;
01059 if ( ssid != 0 )
01060 {
01061 sprintf(tmp_callsign+6, "-%d", ssid);
01062 }
01063
01064 checked_call = fapint_check_kiss_callsign(tmp_callsign);
01065 if ( !checked_call )
01066 {
01067 sprintf(output, "Invalid callsign in header (%s).", tmp_callsign);
01068 output_len = strlen(output)+1;
01069 retval = 0;
01070 break;
01071 }
01072
01073 if ( header_len == 7 )
01074 {
01075
01076 dst_callsign = checked_call;
01077 }
01078 else if ( header_len == 14 )
01079 {
01080
01081 sprintf(output, "%s>%s", checked_call, dst_callsign);
01082 output_len = strlen(checked_call) + 1 + strlen(dst_callsign);
01083 free(dst_callsign);
01084 free(checked_call);
01085 }
01086 else if ( header_len > 14 )
01087 {
01088
01089 sprintf(output+output_len, "%s", checked_call);
01090 output_len += strlen(checked_call);
01091 free(checked_call);
01092
01093 if ( charri & 0x80 )
01094 {
01095 output[output_len] = '*';
01096 output_len++;
01097 }
01098 digi_count++;
01099 }
01100 else
01101 {
01102 sprintf(output, "Internal error.");
01103 output_len = strlen(output)+1;
01104 retval = 0;
01105 break;
01106 }
01107
01108 if ( part_no == 0 )
01109 {
01110
01111 if ( digi_count >= 8 )
01112 {
01113 sprintf(output, "Too many digis.");
01114 output_len = strlen(output)+1;
01115 retval = 0;
01116 break;
01117 }
01118 output[output_len] = ',';
01119 output_len++;
01120 }
01121 else
01122 {
01123
01124 output[output_len] = ':';
01125 output_len++;
01126 }
01127 j = 0;
01128 memset(tmp_callsign, 0, 10);
01129 continue;
01130 }
01131
01132
01133 tmp_callsign[j] = (charri & 0xff) >> 1;
01134 ++j;
01135 }
01136 else if ( part_no == 1 )
01137 {
01138
01139 if ( (charri & 0xff) != AX25_FRAME_UI )
01140 {
01141 retval = 0;
01142 break;
01143 }
01144 part_no = 2;
01145 }
01146 else if ( part_no == 2 )
01147 {
01148
01149 if ( (charri & 0xff) != AX25_PID_APRS )
01150 {
01151 retval = 0;
01152 break;
01153 }
01154 part_no = 3;
01155 }
01156 else
01157 {
01158 output[output_len] = charri;
01159 output_len++;
01160 }
01161 }
01162
01163
01164 if ( output_len > *tnc2frame_len ) output_len = *tnc2frame_len;
01165 memcpy(tnc2frame, output, output_len);
01166 *tnc2frame_len = output_len;
01167
01168 return retval;
01169 }
01170
01171
01172
01173 int fap_tnc2_to_kiss(char const* tnc2frame, unsigned int tnc2frame_len, unsigned int const tnc_id,
01174 char* kissframe, unsigned int* kissframe_len)
01175 {
01176 char ax25frame[2*FRAME_MAXLEN];
01177 unsigned int ax25frame_len;
01178 int i;
01179
01180
01181 ax25frame_len = 2*FRAME_MAXLEN-2;
01182 memset(ax25frame, 0, 2);
01183
01184
01185 if ( !fap_tnc2_to_ax25(tnc2frame, tnc2frame_len, ax25frame+2, &ax25frame_len) )
01186 {
01187 strcpy(kissframe, ax25frame);
01188 *kissframe_len = strlen(kissframe);
01189 return 0;
01190 }
01191 ax25frame_len += 2;
01192
01193
01194 if ( *kissframe_len <= ax25frame_len )
01195 {
01196 return 0;
01197 }
01198
01199
01200 *kissframe_len = 2;
01201 for ( i = 2; i < ax25frame_len; ++i )
01202 {
01203 if ( (ax25frame[i] & 0xff) == FEND || (ax25frame[i] & 0xff) == FESC )
01204 {
01205 kissframe[*kissframe_len] = FESC;
01206 (*kissframe_len)++;
01207 if ( (ax25frame[i] & 0xff) == FEND )
01208 {
01209 kissframe[*kissframe_len] = TFEND;
01210 }
01211 else
01212 {
01213 kissframe[*kissframe_len] = TFESC;
01214 }
01215 (*kissframe_len)++;
01216 }
01217 else
01218 {
01219 kissframe[*kissframe_len] = ax25frame[i];
01220 (*kissframe_len)++;
01221 }
01222 }
01223
01224
01225 kissframe[0] = FEND;
01226 kissframe[1] = tnc_id;
01227 kissframe[*kissframe_len] = FEND;
01228 (*kissframe_len)++;
01229
01230 return 1;
01231 }
01232
01233
01234
01235 int fap_tnc2_to_ax25(char const* tnc2frame, unsigned int tnc2frame_len,
01236 char* ax25frame, unsigned int* ax25frame_len)
01237 {
01238 char input[FRAME_MAXLEN];
01239
01240 char output[2*FRAME_MAXLEN];
01241 unsigned int output_len = 0;
01242
01243 char *header = NULL, *digipeaters = NULL, *body = NULL;
01244 unsigned int digi_count, body_len;
01245
01246 char sender[6], sender_ssid[4], receiver[6], receiver_ssid[4];
01247 int sender_ssid_num = 0, receiver_ssid_num = 0;
01248
01249 char digicall[6], digicall_ssid[4], hbit;
01250 int digicall_ssid_num = 0;
01251
01252 int retval = 1, len, i;
01253 char* tmp_str;
01254
01255 unsigned int const matchcount = 6;
01256 regmatch_t matches[matchcount];
01257
01258
01259
01260 if ( !tnc2frame || !tnc2frame_len || tnc2frame_len >= FRAME_MAXLEN || !ax25frame || !ax25frame_len )
01261 {
01262 return 0;
01263 }
01264
01265
01266 memset(input, 0, FRAME_MAXLEN);
01267 memcpy(input, tnc2frame, tnc2frame_len );
01268
01269
01270 if ( regexec(&fapint_regex_kiss_hdrbdy, input, matchcount, (regmatch_t*)&matches, 0) == 0 )
01271 {
01272 len = matches[1].rm_eo - matches[1].rm_so;
01273 header = malloc(len+1);
01274 if ( !header ) return 0;
01275 memcpy(header, input+matches[1].rm_so, len);
01276 header[len] = 0;
01277
01278 body_len = matches[2].rm_eo - matches[2].rm_so;
01279 body = malloc(body_len);
01280 if ( !body )
01281 {
01282 free(header);
01283 return 0;
01284 }
01285 memcpy(body, input+matches[2].rm_so, body_len);
01286 }
01287 else
01288 {
01289 sprintf(output, "Failed to separate header and body of TNC-2 packet.");
01290 output_len = strlen(output)+1;
01291 if ( output_len > *ax25frame_len ) output_len = *ax25frame_len;
01292 strcpy(ax25frame, output);
01293 *ax25frame_len = output_len;
01294 return 0;
01295 }
01296
01297
01298 if ( regexec(&fapint_regex_hdr_detail, header, matchcount, (regmatch_t*)&matches, 0) == 0 )
01299 {
01300 len = matches[1].rm_eo - matches[1].rm_so;
01301 memset(sender, ' ', 6);
01302 memcpy(sender, header+matches[1].rm_so, len);
01303
01304 len = matches[2].rm_eo - matches[2].rm_so;
01305 memset(sender_ssid, 0, 4);
01306 if ( len )
01307 {
01308 memcpy(sender_ssid, header+matches[2].rm_so, len);
01309 }
01310
01311 len = matches[3].rm_eo - matches[3].rm_so;
01312 memset(receiver, ' ', 6);
01313 memcpy(receiver, header+matches[3].rm_so, len);
01314
01315 len = matches[4].rm_eo - matches[4].rm_so;
01316 memset(receiver_ssid, 0, 4);
01317 if ( len )
01318 {
01319 memcpy(receiver_ssid, header+matches[4].rm_so, len);
01320 }
01321
01322 len = matches[5].rm_eo - matches[5].rm_so;
01323 if ( len )
01324 {
01325 digipeaters = malloc(len+5);
01326 if ( !digipeaters )
01327 {
01328 free(header);
01329 free(body);
01330 return 0;
01331 }
01332 memcpy(digipeaters, header+matches[5].rm_so, len);
01333 digipeaters[len] = 0;
01334 }
01335 }
01336 else
01337 {
01338 free(header);
01339 free(body);
01340 return 0;
01341 }
01342 free(header);
01343
01344
01345 while ( 1 )
01346 {
01347
01348 if ( sender_ssid[0] == '-' )
01349 {
01350 sender_ssid_num = 0 - atoi(sender_ssid);
01351 if ( sender_ssid_num > 15 )
01352 {
01353 retval = 0;
01354 break;
01355 }
01356 }
01357 if ( receiver_ssid[0] == '-' )
01358 {
01359 receiver_ssid_num = 0 - atoi(receiver_ssid);
01360 if ( receiver_ssid_num > 15 )
01361 {
01362 retval = 0;
01363 break;
01364 }
01365 }
01366
01367
01368 for ( i = 0; i < 6; ++i )
01369 {
01370 output[output_len] = receiver[i] << 1;
01371 output_len++;
01372 }
01373 output[output_len] = 0xe0 | (receiver_ssid_num << 1);
01374 output_len++;
01375 for ( i = 0; i < 6; ++i )
01376 {
01377 output[output_len] = sender[i] << 1;
01378 output_len++;
01379 }
01380 if ( digipeaters )
01381 {
01382 output[output_len] = 0x60 | (sender_ssid_num << 1);
01383 }
01384 else
01385 {
01386 output[output_len] = 0x61 | (sender_ssid_num << 1);
01387 }
01388 output_len++;
01389
01390
01391 if ( digipeaters )
01392 {
01393
01394 tmp_str = strtok(digipeaters+1, ",");
01395 digi_count = 0;
01396 while ( tmp_str != NULL )
01397 {
01398
01399 if ( regexec(&fapint_regex_kiss_digi, tmp_str, matchcount, (regmatch_t*)&matches, 0) == 0 )
01400 {
01401
01402 len = matches[1].rm_eo - matches[1].rm_so;
01403 memset(digicall, ' ', 6);
01404 memcpy(digicall, tmp_str+matches[1].rm_so, len);
01405
01406
01407 digicall_ssid_num = 0;
01408 len = matches[2].rm_eo - matches[2].rm_so;
01409 if ( len )
01410 {
01411 memset(digicall_ssid, 0, 4);
01412 memcpy(digicall_ssid, tmp_str+matches[2].rm_so, len);
01413
01414 digicall_ssid_num = 0 - atoi(digicall_ssid);
01415 if ( digicall_ssid_num > 15 )
01416 {
01417 retval = 0;
01418 break;
01419 }
01420 }
01421
01422
01423 hbit = 0x00;
01424 if ( tmp_str[matches[3].rm_so] == '*' )
01425 {
01426 hbit = 0x80;
01427 }
01428
01429
01430 tmp_str = strtok(NULL, ",");
01431
01432
01433 for ( i = 0; i < 6; ++i )
01434 {
01435 output[output_len] = digicall[i] << 1;
01436 output_len++;
01437 }
01438
01439 if ( tmp_str )
01440 {
01441
01442 output[output_len] = 0x60 | (digicall_ssid_num << 1);
01443 }
01444 else
01445 {
01446
01447 output[output_len] = 0x61 | (digicall_ssid_num << 1);
01448 }
01449 output_len++;
01450 }
01451 else
01452 {
01453
01454 retval = 0;
01455 break;
01456 }
01457 }
01458 }
01459
01460
01461 break;
01462 }
01463 if ( digipeaters ) free(digipeaters);
01464
01465
01466
01467 output[output_len] = AX25_FRAME_UI;
01468 output_len++;
01469 output[output_len] = AX25_PID_APRS;
01470 output_len++;
01471
01472
01473 memcpy(output+output_len, body, body_len);
01474 output_len += body_len;
01475 free(body);
01476
01477
01478 if ( !retval )
01479 {
01480 return 0;
01481 }
01482
01483
01484 if ( output_len > *ax25frame_len ) output_len = *ax25frame_len;
01485 memcpy(ax25frame, output, output_len);
01486 *ax25frame_len = output_len;
01487 return 1;
01488 }
01489
01490
01491
01492 void fap_init()
01493 {
01494 if ( !fapint_initialized )
01495 {
01496
01497 regcomp(&fapint_regex_header, "^([A-Z0-9\\-]{1,9})>(.*)$", REG_EXTENDED);
01498 regcomp(&fapint_regex_ax25call, "^([A-Z0-9]{1,6})(-[0-9]{1,2}|())$", REG_EXTENDED);
01499 regcomp(&fapint_regex_digicall, "^([a-zA-Z0-9-]{1,9})([*]?)$", REG_EXTENDED);
01500 regcomp(&fapint_regex_digicallv6, "^([0-9A-F]{32})$", REG_EXTENDED|REG_NOSUB);
01501
01502 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);
01503 regcomp(&fapint_regex_normalamb, "^([0-9]{0,4})( {0,4})$", REG_EXTENDED);
01504 regcomp(&fapint_regex_timestamp, "^([0-9]{2})([0-9]{2})([0-9]{2})([zh\\/])", REG_EXTENDED);
01505
01506 regcomp(&fapint_regex_mice_dstcall, "^[0-9A-LP-Z]{3}[0-9LP-Z]{3}$", REG_EXTENDED|REG_NOSUB);
01507 regcomp(&fapint_regex_mice_body, "^[\\/\\\\A-Z0-9]", REG_EXTENDED|REG_NOSUB);
01508 regcomp(&fapint_regex_mice_amb, "^([0-9]+)(_*)$", REG_EXTENDED);
01509
01510 regcomp(&fapint_regex_comment, "^([0-9\\. ]{3})\\/([0-9\\. ]{3})", REG_EXTENDED|REG_NOSUB);
01511 regcomp(&fapint_regex_phgr, "^PHG([0-9].[0-9]{2}[1-9A-Z])\\/", REG_EXTENDED|REG_NOSUB);
01512 regcomp(&fapint_regex_phg, "^PHG([0-9].[0-9]{2})", REG_EXTENDED|REG_NOSUB);
01513 regcomp(&fapint_regex_rng, "^RNG([0-9]{4})", REG_EXTENDED|REG_NOSUB);
01514 regcomp(&fapint_regex_altitude, "\\/A=(-[0-9]{5}|[0-9]{6})", REG_EXTENDED);
01515
01516 regcomp(&fapint_regex_mes_dst, "^:([A-Za-z0-9_ -]{9}):", REG_EXTENDED);
01517 regcomp(&fapint_regex_mes_ack, "^ack([A-Za-z0-9}]{1,5}) *$", REG_EXTENDED);
01518 regcomp(&fapint_regex_mes_nack, "^rej([A-Za-z0-9}]{1,5}) *$", REG_EXTENDED);
01519
01520 regcomp(&fapint_regex_wx1, "^_{0,1}([0-9 \\.\\-]{3})\\/([0-9 \\.]{3})g([0-9 \\.]+)t(-{0,1}[0-9 \\.]+)", REG_EXTENDED);
01521 regcomp(&fapint_regex_wx2, "^_{0,1}c([0-9 \\.\\-]{3})s([0-9 \\.]{3})g([0-9 \\.]+)t(-{0,1}[0-9 \\.]+)", REG_EXTENDED);
01522 regcomp(&fapint_regex_wx3, "^_{0,1}([0-9 \\.\\-]{3})\\/([0-9 \\.]{3})t(-{0,1}[0-9 \\.]+)", REG_EXTENDED);
01523 regcomp(&fapint_regex_wx4, "^_{0,1}([0-9 \\.\\-]{3})\\/([0-9 \\.]{3})g([0-9 \\.]+)", REG_EXTENDED);
01524 regcomp(&fapint_regex_wx5, "^g([0-9]+)t(-?[0-9 \\.]{1,3})", REG_EXTENDED);
01525
01526 regcomp(&fapint_regex_wx_r1, "r([0-9]{1,3})", REG_EXTENDED);
01527 regcomp(&fapint_regex_wx_r24, "p([0-9]{1,3})", REG_EXTENDED);
01528 regcomp(&fapint_regex_wx_rami, "P([0-9]{1,3})", REG_EXTENDED);
01529
01530 regcomp(&fapint_regex_wx_humi, "h([0-9]{1,3})", REG_EXTENDED);
01531 regcomp(&fapint_regex_wx_pres, "b([0-9]{4,5})", REG_EXTENDED);
01532 regcomp(&fapint_regex_wx_lumi, "([lL])([0-9]{1,3})", REG_EXTENDED);
01533 regcomp(&fapint_regex_wx_what, "v([\\-\\+]{0,1}[0-9]+)", REG_EXTENDED);
01534
01535 regcomp(&fapint_regex_wx_snow, "s([0-9]+)", REG_EXTENDED);
01536 regcomp(&fapint_regex_wx_rrc, "#([0-9]+)", REG_EXTENDED);
01537 regcomp(&fapint_regex_wx_any, "^([rPphblLs#][\\. ]{1,5})+", REG_EXTENDED);
01538 regcomp(&fapint_regex_wx_soft, "^[a-zA-Z0-9\\-\\_]{3,5}$", REG_EXTENDED|REG_NOSUB);
01539
01540 regcomp(&fapint_regex_nmea_chksum, "^(.+)\\*([0-9A-F]{2})$", REG_EXTENDED);
01541 regcomp(&fapint_regex_nmea_dst, "^(GPS|SPC)([A-Z0-9]{2,3})", REG_EXTENDED);
01542 regcomp(&fapint_regex_nmea_time, "^[:space:]*([0-9]{2})([0-9]{2})([0-9]{2})(()|\\.[0-9]+)[:space:]*$", REG_EXTENDED);
01543 regcomp(&fapint_regex_nmea_date, "^[:space:]*([0-9]{2})([0-9]{2})([0-9]{2})[:space:]*$", REG_EXTENDED);
01544
01545 regcomp(&fapint_regex_nmea_specou, "^[:space:]*([0-9]+(()|\\.[0-9]+))[:space:]*$", REG_EXTENDED);
01546 regcomp(&fapint_regex_nmea_fix, "^[:space:]*([0-9]+)[:space:]*$", REG_EXTENDED);
01547 regcomp(&fapint_regex_nmea_altitude, "^(-?[0-9]+(()|\\.[0-9]+))$", REG_EXTENDED);
01548 regcomp(&fapint_regex_nmea_flag, "^[:space:]*([NSEWnsew])[:space:]*$", REG_EXTENDED);
01549 regcomp(&fapint_regex_nmea_coord, "^[:space:]*([0-9]{1,3})([0-5][0-9]\\.([0-9]+))[:space:]*$", REG_EXTENDED);
01550
01551 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);
01552 regcomp(&fapint_regex_peet_splitter, "^([0-9a-f]{4}|----)", REG_EXTENDED|REG_ICASE);
01553 regcomp(&fapint_regex_kiss_callsign, "^([A-Z0-9]+) *(-[0-9]+)?$", REG_EXTENDED);
01554
01555 regcomp(&fapint_regex_detect_comp, "^[\\/\\\\A-Za-j]$", REG_EXTENDED|REG_NOSUB);
01556 regcomp(&fapint_regex_detect_wx, "^_([0-9]{8})c[- .0-9]{1,3}s[- .0-9]{1,3}", REG_EXTENDED|REG_NOSUB);
01557 regcomp(&fapint_regex_detect_telem, "^T#(.*?),(.*)$", REG_EXTENDED|REG_NOSUB);
01558 regcomp(&fapint_regex_detect_exp, "^\\{\\{", REG_EXTENDED|REG_NOSUB);
01559
01560 regcomp(&fapint_regex_kiss_hdrbdy, "^([A-Z0-9,*>-]+):(.+)$", REG_EXTENDED);
01561 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);
01562 regcomp(&fapint_regex_kiss_digi, "^([A-Z0-9]{1,6})(-[0-9]{1,2})?(\\*)?$", REG_EXTENDED);
01563
01564 regcomp(&fapint_regex_hopcount1, "^([A-Z0-9-]+)\\*$", REG_EXTENDED);
01565 regcomp(&fapint_regex_hopcount2, "^WIDE([1-7])-([0-7])$", REG_EXTENDED);
01566
01567
01568
01569 fapint_initialized = 1;
01570 }
01571 }
01572
01573
01574
01575 void fap_cleanup()
01576 {
01577 if ( fapint_initialized )
01578 {
01579
01580 regfree(&fapint_regex_header);
01581 regfree(&fapint_regex_ax25call);
01582 regfree(&fapint_regex_digicall);
01583 regfree(&fapint_regex_digicallv6);
01584
01585 regfree(&fapint_regex_normalpos);
01586 regfree(&fapint_regex_normalamb);
01587 regfree(&fapint_regex_timestamp);
01588
01589 regfree(&fapint_regex_mice_dstcall);
01590 regfree(&fapint_regex_mice_body);
01591 regfree(&fapint_regex_mice_amb);
01592
01593 regfree(&fapint_regex_comment);
01594 regfree(&fapint_regex_phgr);
01595 regfree(&fapint_regex_phg);
01596 regfree(&fapint_regex_rng);
01597 regfree(&fapint_regex_altitude);
01598
01599 regfree(&fapint_regex_mes_dst);
01600 regfree(&fapint_regex_mes_ack);
01601 regfree(&fapint_regex_mes_nack);
01602
01603 regfree(&fapint_regex_wx1);
01604 regfree(&fapint_regex_wx2);
01605 regfree(&fapint_regex_wx3);
01606 regfree(&fapint_regex_wx4);
01607 regfree(&fapint_regex_wx5);
01608
01609 regfree(&fapint_regex_wx_r1);
01610 regfree(&fapint_regex_wx_r24);
01611 regfree(&fapint_regex_wx_rami);
01612
01613 regfree(&fapint_regex_wx_humi);
01614 regfree(&fapint_regex_wx_pres);
01615 regfree(&fapint_regex_wx_lumi);
01616 regfree(&fapint_regex_wx_what);
01617
01618 regfree(&fapint_regex_wx_snow);
01619 regfree(&fapint_regex_wx_rrc);
01620 regfree(&fapint_regex_wx_any);
01621 regfree(&fapint_regex_wx_soft);
01622
01623 regfree(&fapint_regex_nmea_chksum);
01624 regfree(&fapint_regex_nmea_dst);
01625 regfree(&fapint_regex_nmea_time);
01626 regfree(&fapint_regex_nmea_date);
01627
01628 regfree(&fapint_regex_nmea_specou);
01629 regfree(&fapint_regex_nmea_fix);
01630 regfree(&fapint_regex_nmea_altitude);
01631 regfree(&fapint_regex_nmea_flag);
01632 regfree(&fapint_regex_nmea_coord);
01633
01634 regfree(&fapint_regex_telemetry);
01635 regfree(&fapint_regex_peet_splitter);
01636 regfree(&fapint_regex_kiss_callsign);
01637
01638 regfree(&fapint_regex_detect_comp);
01639 regfree(&fapint_regex_detect_wx);
01640 regfree(&fapint_regex_detect_telem);
01641 regfree(&fapint_regex_detect_exp);
01642
01643 regfree(&fapint_regex_kiss_hdrbdy);
01644 regfree(&fapint_regex_hdr_detail);
01645 regfree(&fapint_regex_kiss_digi);
01646
01647 regfree(&fapint_regex_hopcount1);
01648 regfree(&fapint_regex_hopcount2);
01649
01650
01651 fapint_initialized = 0;
01652 }
01653 }
01654
01655
01656
01657 void fap_free(fap_packet_t* packet)
01658 {
01659 unsigned int i;
01660
01661 if ( packet == NULL )
01662 {
01663 return;
01664 }
01665
01666 if ( packet->error_code ) { free(packet->error_code); }
01667 if ( packet->error_message ) { free(packet->error_message); }
01668 if ( packet->type ) { free(packet->type); }
01669
01670 if ( packet->orig_packet ) { free(packet->orig_packet); }
01671
01672 if ( packet->header ) { free(packet->header); }
01673 if ( packet->body ) { free(packet->body); }
01674 if ( packet->src_callsign ) { free(packet->src_callsign); }
01675 if ( packet->dst_callsign ) { free(packet->dst_callsign); }
01676 for ( i = 0; i < packet->path_len; ++i )
01677 {
01678 if ( packet->path[i] ) { free(packet->path[i]); }
01679 }
01680 if ( packet->path ) { free(packet->path); }
01681
01682 if ( packet->latitude ) { free(packet->latitude); }
01683 if ( packet->longitude ) { free(packet->longitude); }
01684 if ( packet->format ) { free(packet->format); }
01685 if ( packet->pos_resolution ) { free(packet->pos_resolution); }
01686 if ( packet->pos_ambiguity ) { free(packet->pos_ambiguity); }
01687
01688 if ( packet->altitude ) { free(packet->altitude); }
01689 if ( packet->course ) { free(packet->course); }
01690 if ( packet->speed ) { free(packet->speed); }
01691
01692 if ( packet->messaging ) { free(packet->messaging); }
01693 if ( packet->destination ) { free(packet->destination); }
01694 if ( packet->message ) { free(packet->message); }
01695 if ( packet->message_ack ) { free(packet->message_ack); }
01696 if ( packet->message_nack ) { free(packet->message_nack); }
01697 if ( packet->message_id ) { free(packet->message_id); }
01698 if ( packet->comment ) { free(packet->comment); }
01699
01700 if ( packet->object_or_item_name ) { free(packet->object_or_item_name); }
01701 if ( packet->alive ) { free(packet->alive); }
01702
01703 if ( packet->gps_fix_status ) { free(packet->gps_fix_status); }
01704 if ( packet->radio_range ) { free(packet->radio_range); }
01705 if ( packet->phg ) { free(packet->phg); }
01706 if ( packet->timestamp ) { free(packet->timestamp); }
01707 if ( packet->nmea_checksum_ok ) { free(packet->nmea_checksum_ok); }
01708
01709 if ( packet->wx_report )
01710 {
01711 if ( packet->wx_report->wind_gust ) { free(packet->wx_report->wind_gust); }
01712 if ( packet->wx_report->wind_dir ) { free(packet->wx_report->wind_dir); }
01713 if ( packet->wx_report->wind_speed ) { free(packet->wx_report->wind_speed); }
01714
01715 if ( packet->wx_report->temp ) { free(packet->wx_report->temp); }
01716 if ( packet->wx_report->temp_in ) { free(packet->wx_report->temp_in); }
01717
01718 if ( packet->wx_report->rain_1h ) { free(packet->wx_report->rain_1h); }
01719 if ( packet->wx_report->rain_24h ) { free(packet->wx_report->rain_24h); }
01720 if ( packet->wx_report->rain_midnight ) { free(packet->wx_report->rain_midnight); }
01721
01722 if ( packet->wx_report->humidity ) { free(packet->wx_report->humidity); }
01723 if ( packet->wx_report->humidity_in ) { free(packet->wx_report->humidity_in); }
01724
01725 if ( packet->wx_report->pressure ) { free(packet->wx_report->pressure); }
01726 if ( packet->wx_report->luminosity ) { free(packet->wx_report->luminosity); }
01727
01728 if ( packet->wx_report->snow_24h ) { free(packet->wx_report->snow_24h); }
01729
01730 if ( packet->wx_report->soft ) { free(packet->wx_report->soft); }
01731
01732 free(packet->wx_report);
01733 }
01734
01735 if ( packet->telemetry ) { free(packet->telemetry); }
01736
01737 if ( packet->messagebits ) { free(packet->messagebits); }
01738 if ( packet->status ) { free(packet->status); }
01739 for ( i = 0; i < packet->capabilities_len*2; i += 2 )
01740 {
01741 if ( packet->capabilities[i] ) { free(packet->capabilities[i]); }
01742 if ( packet->capabilities[i+1] ) { free(packet->capabilities[i+1]); }
01743 }
01744 if ( packet->capabilities ) { free(packet->capabilities); }
01745
01746 free(packet);
01747 }