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