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