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
01168
01169 if ( !fap_tnc2_to_ax25(tnc2frame, tnc2frame_len, ax25frame+2, &ax25frame_len) )
01170 {
01171 strcpy(kissframe, ax25frame);
01172 *kissframe_len = ax25frame_len;
01173 return 0;
01174 }
01175 ax25frame_len += 2;
01176
01177
01178 *kissframe_len = 0;
01179 for ( i = 0; i < ax25frame_len; ++i )
01180 {
01181 if ( (ax25frame[i] & 0xff) == FEND || (ax25frame[i] & 0xff) == FESC )
01182 {
01183 kissframe[*kissframe_len] = FESC;
01184 (*kissframe_len)++;
01185 if ( (ax25frame[i] & 0xff) == FEND )
01186 {
01187 kissframe[*kissframe_len] = TFEND;
01188 }
01189 else
01190 {
01191 kissframe[*kissframe_len] = TFESC;
01192 }
01193 (*kissframe_len)++;
01194 }
01195 else
01196 {
01197 kissframe[*kissframe_len] = ax25frame[i];
01198 (*kissframe_len)++;
01199 }
01200 }
01201
01202
01203 kissframe[0] = FEND;
01204 kissframe[1] = tnc_id;
01205 kissframe[*kissframe_len] = FEND;
01206 (*kissframe_len)++;
01207
01208 return 1;
01209 }
01210
01211
01212
01213 int fap_tnc2_to_ax25(char const* tnc2frame, unsigned int tnc2frame_len,
01214 char* ax25frame, unsigned int* ax25frame_len)
01215 {
01216 char input[FRAME_MAXLEN];
01217
01218 char output[2*FRAME_MAXLEN];
01219 unsigned int output_len = 0;
01220
01221 char *header = NULL, *digipeaters = NULL, *body = NULL;
01222 unsigned int digi_count, body_len;
01223
01224 char sender[6], sender_ssid[4], receiver[6], receiver_ssid[4];
01225 int sender_ssid_num = 0, receiver_ssid_num = 0;
01226
01227 char digicall[6], digicall_ssid[4], hbit;
01228 int digicall_ssid_num = 0;
01229
01230 int retval = 1, len, i;
01231 char* tmp_str;
01232
01233 unsigned int const matchcount = 6;
01234 regmatch_t matches[matchcount];
01235
01236
01237
01238 if ( !tnc2frame || !tnc2frame_len || tnc2frame_len >= FRAME_MAXLEN || !ax25frame || !ax25frame_len )
01239 {
01240 return 0;
01241 }
01242
01243
01244 memset(input, 0, FRAME_MAXLEN);
01245 memcpy(input, tnc2frame, tnc2frame_len );
01246
01247
01248 if ( regexec(&fapint_regex_kiss_hdrbdy, input, matchcount, (regmatch_t*)&matches, 0) == 0 )
01249 {
01250 len = matches[1].rm_eo - matches[1].rm_so;
01251 header = malloc(len+1);
01252 if ( !header ) return 0;
01253 memcpy(header, input+matches[1].rm_so, len);
01254 header[len] = 0;
01255
01256 body_len = matches[2].rm_eo - matches[2].rm_so;
01257 body = malloc(body_len);
01258 if ( !body )
01259 {
01260 free(header);
01261 return 0;
01262 }
01263 memcpy(body, input+matches[2].rm_so, body_len);
01264 }
01265 else
01266 {
01267 sprintf(output, "Failed to separate header and body of TNC-2 packet.");
01268 output_len = strlen(output)+1;
01269 if ( output_len > *ax25frame_len ) output_len = *ax25frame_len;
01270 strcpy(ax25frame, output);
01271 *ax25frame_len = output_len;
01272 return 0;
01273 }
01274
01275
01276 if ( regexec(&fapint_regex_hdr_detail, header, matchcount, (regmatch_t*)&matches, 0) == 0 )
01277 {
01278 len = matches[1].rm_eo - matches[1].rm_so;
01279 memset(sender, ' ', 6);
01280 memcpy(sender, header+matches[1].rm_so, len);
01281
01282 len = matches[2].rm_eo - matches[2].rm_so;
01283 memset(sender_ssid, 0, 4);
01284 if ( len )
01285 {
01286 memcpy(sender_ssid, header+matches[2].rm_so, len);
01287 }
01288
01289 len = matches[3].rm_eo - matches[3].rm_so;
01290 memset(receiver, ' ', 6);
01291 memcpy(receiver, header+matches[3].rm_so, len);
01292
01293 len = matches[4].rm_eo - matches[4].rm_so;
01294 memset(receiver_ssid, 0, 4);
01295 if ( len )
01296 {
01297 memcpy(receiver_ssid, header+matches[4].rm_so, len);
01298 }
01299
01300 len = matches[5].rm_eo - matches[5].rm_so;
01301 if ( len )
01302 {
01303 digipeaters = malloc(len+5);
01304 if ( !digipeaters )
01305 {
01306 free(header);
01307 free(body);
01308 return 0;
01309 }
01310 memcpy(digipeaters, header+matches[5].rm_so, len);
01311 digipeaters[len] = 0;
01312 }
01313 }
01314 else
01315 {
01316 free(header);
01317 free(body);
01318 return 0;
01319 }
01320 free(header);
01321
01322
01323 while ( 1 )
01324 {
01325
01326 if ( sender_ssid[0] == '-' )
01327 {
01328 sender_ssid_num = 0 - atoi(sender_ssid);
01329 if ( sender_ssid_num > 15 )
01330 {
01331 retval = 0;
01332 break;
01333 }
01334 }
01335 if ( receiver_ssid[0] == '-' )
01336 {
01337 receiver_ssid_num = 0 - atoi(receiver_ssid);
01338 if ( receiver_ssid_num > 15 )
01339 {
01340 retval = 0;
01341 break;
01342 }
01343 }
01344
01345
01346 for ( i = 0; i < 6; ++i )
01347 {
01348 output[output_len] = receiver[i] << 1;
01349 output_len++;
01350 }
01351 output[output_len] = 0xe0 | (receiver_ssid_num << 1);
01352 output_len++;
01353 for ( i = 0; i < 6; ++i )
01354 {
01355 output[output_len] = sender[i] << 1;
01356 output_len++;
01357 }
01358 if ( digipeaters )
01359 {
01360 output[output_len] = 0x60 | (sender_ssid_num << 1);
01361 }
01362 else
01363 {
01364 output[output_len] = 0x61 | (sender_ssid_num << 1);
01365 }
01366 output_len++;
01367
01368
01369 if ( digipeaters )
01370 {
01371
01372 tmp_str = strtok(digipeaters+1, ",");
01373 digi_count = 0;
01374 while ( tmp_str != NULL )
01375 {
01376
01377 if ( regexec(&fapint_regex_kiss_digi, tmp_str, matchcount, (regmatch_t*)&matches, 0) == 0 )
01378 {
01379
01380 len = matches[1].rm_eo - matches[1].rm_so;
01381 memset(digicall, ' ', 6);
01382 memcpy(digicall, tmp_str+matches[1].rm_so, len);
01383
01384
01385 digicall_ssid_num = 0;
01386 len = matches[2].rm_eo - matches[2].rm_so;
01387 if ( len )
01388 {
01389 memset(digicall_ssid, 0, 4);
01390 memcpy(digicall_ssid, tmp_str+matches[2].rm_so, len);
01391
01392 digicall_ssid_num = 0 - atoi(digicall_ssid);
01393 if ( digicall_ssid_num > 15 )
01394 {
01395 retval = 0;
01396 break;
01397 }
01398 }
01399
01400
01401 hbit = 0x00;
01402 if ( tmp_str[matches[3].rm_so] == '*' )
01403 {
01404 hbit = 0x80;
01405 }
01406
01407
01408 tmp_str = strtok(NULL, ",");
01409
01410
01411 for ( i = 0; i < 6; ++i )
01412 {
01413 output[output_len] = digicall[i] << 1;
01414 output_len++;
01415 }
01416
01417 if ( tmp_str )
01418 {
01419
01420 output[output_len] = 0x60 | (digicall_ssid_num << 1);
01421 }
01422 else
01423 {
01424
01425 output[output_len] = 0x61 | (digicall_ssid_num << 1);
01426 }
01427 output_len++;
01428 }
01429 else
01430 {
01431
01432 retval = 0;
01433 break;
01434 }
01435 }
01436 }
01437
01438
01439 break;
01440 }
01441 if ( digipeaters ) free(digipeaters);
01442
01443
01444
01445 output[output_len] = AX25_FRAME_UI;
01446 output_len++;
01447 output[output_len] = AX25_PID_APRS;
01448 output_len++;
01449
01450
01451 memcpy(output+output_len, body, body_len);
01452 output_len += body_len;
01453 free(body);
01454
01455
01456 if ( !retval )
01457 {
01458 return 0;
01459 }
01460
01461
01462 if ( output_len > *ax25frame_len ) output_len = *ax25frame_len;
01463 memcpy(ax25frame, output, output_len);
01464 *ax25frame_len = output_len;
01465 return 1;
01466 }
01467
01468
01469
01470 void fap_init()
01471 {
01472 if ( !fapint_initialized )
01473 {
01474
01475 regcomp(&fapint_regex_header, "^([A-Z0-9\\-]{1,9})>(.*)$", REG_EXTENDED);
01476 regcomp(&fapint_regex_ax25call, "^([A-Z0-9]{1,6})(-[0-9]{1,2}|())$", REG_EXTENDED);
01477 regcomp(&fapint_regex_digicall, "^([a-zA-Z0-9-]{1,9})([*]?)$", REG_EXTENDED);
01478
01479 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);
01480 regcomp(&fapint_regex_normalamb, "^([0-9]{0,4})( {0,4})$", REG_EXTENDED);
01481 regcomp(&fapint_regex_timestamp, "^([0-9]{2})([0-9]{2})([0-9]{2})([zh\\/])", REG_EXTENDED);
01482
01483 regcomp(&fapint_regex_mice_dstcall, "^[0-9A-LP-Z]{3}[0-9LP-Z]{3}$", REG_EXTENDED|REG_NOSUB);
01484 regcomp(&fapint_regex_mice_body, "^[\\/\\\\A-Z0-9]", REG_EXTENDED|REG_NOSUB);
01485 regcomp(&fapint_regex_mice_amb, "^([0-9]+)(_*)$", REG_EXTENDED);
01486
01487 regcomp(&fapint_regex_comment, "^([0-9\\. ]{3})\\/([0-9\\. ]{3})", REG_EXTENDED|REG_NOSUB);
01488 regcomp(&fapint_regex_phgr, "^PHG([0-9].[0-9]{2}[1-9A-Z])\\/", REG_EXTENDED|REG_NOSUB);
01489 regcomp(&fapint_regex_phg, "^PHG([0-9].[0-9]{2})", REG_EXTENDED|REG_NOSUB);
01490 regcomp(&fapint_regex_rng, "^RNG([0-9]{4})", REG_EXTENDED|REG_NOSUB);
01491 regcomp(&fapint_regex_altitude, "\\/A=(-[0-9]{5}|[0-9]{6})", REG_EXTENDED);
01492
01493 regcomp(&fapint_regex_mes_dst, "^:([A-Za-z0-9_ -]{9}):", REG_EXTENDED);
01494 regcomp(&fapint_regex_mes_ack, "^ack([A-Za-z0-9}]{1,5}) *$", REG_EXTENDED);
01495 regcomp(&fapint_regex_mes_nack, "^rej([A-Za-z0-9}]{1,5}) *$", REG_EXTENDED);
01496
01497 regcomp(&fapint_regex_wx1, "^_{0,1}([0-9 \\.\\-]{3})\\/([0-9 \\.]{3})g([0-9 \\.]+)t(-{0,1}[0-9 \\.]+)", REG_EXTENDED);
01498 regcomp(&fapint_regex_wx2, "^_{0,1}c([0-9 \\.\\-]{3})s([0-9 \\.]{3})g([0-9 \\.]+)t(-{0,1}[0-9 \\.]+)", REG_EXTENDED);
01499 regcomp(&fapint_regex_wx3, "^_{0,1}([0-9 \\.\\-]{3})\\/([0-9 \\.]{3})t(-{0,1}[0-9 \\.]+)", REG_EXTENDED);
01500 regcomp(&fapint_regex_wx4, "^_{0,1}([0-9 \\.\\-]{3})\\/([0-9 \\.]{3})g([0-9 \\.]+)", REG_EXTENDED);
01501 regcomp(&fapint_regex_wx5, "^g([0-9]+)t(-?[0-9 \\.]{1,3})", REG_EXTENDED);
01502
01503 regcomp(&fapint_regex_wx_r1, "r([0-9]{1,3})", REG_EXTENDED);
01504 regcomp(&fapint_regex_wx_r24, "p([0-9]{1,3})", REG_EXTENDED);
01505 regcomp(&fapint_regex_wx_rami, "P([0-9]{1,3})", REG_EXTENDED);
01506
01507 regcomp(&fapint_regex_wx_humi, "h([0-9]{1,3})", REG_EXTENDED);
01508 regcomp(&fapint_regex_wx_pres, "b([0-9]{4,5})", REG_EXTENDED);
01509 regcomp(&fapint_regex_wx_lumi, "([lL])([0-9]{1,3})", REG_EXTENDED);
01510 regcomp(&fapint_regex_wx_what, "v([\\-\\+]{0,1}[0-9]+)", REG_EXTENDED);
01511 regcomp(&fapint_regex_wx_snow, "s([0-9]+)", REG_EXTENDED);
01512 regcomp(&fapint_regex_wx_rrc, "#([0-9]+)", REG_EXTENDED);
01513 regcomp(&fapint_regex_wx_any, "^([rPphblLs#][\\. ]{1,5})+", REG_EXTENDED);
01514
01515 regcomp(&fapint_regex_nmea_chksum, "^([:print:]+)\\*([0-9A-F]{2})", REG_EXTENDED);
01516 regcomp(&fapint_regex_nmea_dst, "^(GPS|SPC)([A-Z0-9]{2,3})", REG_EXTENDED);
01517 regcomp(&fapint_regex_nmea_time, "^[:space:]*([0-9]{2})([0-9]{2})([0-9]{2})(()|\\.[0-9]+)[:space:]*$", REG_EXTENDED);
01518 regcomp(&fapint_regex_nmea_date, "^[:space:]*([0-9]{2})([0-9]{2})([0-9]{2})[:space:]*$", REG_EXTENDED);
01519
01520 regcomp(&fapint_regex_nmea_specou, "^[:space:]*([0-9]+(()|\\.[0-9]+))[:space:]*$", REG_EXTENDED);
01521 regcomp(&fapint_regex_nmea_fix, "^[:space:]*([0-9]+)[:space:]*$", REG_EXTENDED);
01522 regcomp(&fapint_regex_nmea_altitude, "^(-?[0-9]+(()|\\.[0-9]+))$", REG_EXTENDED);
01523 regcomp(&fapint_regex_nmea_flag, "^[:space:]*([NSEWnsew])[:space:]*$", REG_EXTENDED);
01524 regcomp(&fapint_regex_nmea_coord, "^[:space:]*([0-9]{1,3})([0-5][0-9]\\.([0-9]+))[:space:]*$", REG_EXTENDED);
01525
01526 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);
01527 regcomp(&fapint_regex_peet_splitter, "^([0-9a-f]{4}|----)", REG_EXTENDED|REG_ICASE);
01528 regcomp(&fapint_regex_kiss_callsign, "^([A-Z0-9]+) *(-[0-9]+)?$", REG_EXTENDED);
01529
01530 regcomp(&fapint_regex_detect_comp, "^[\\/\\\\A-Za-j]$", REG_EXTENDED|REG_NOSUB);
01531 regcomp(&fapint_regex_detect_wx, "^_([0-9]{8})c[- .0-9]{1,3}s[- .0-9]{1,3}", REG_EXTENDED|REG_NOSUB);
01532 regcomp(&fapint_regex_detect_telem, "^T#(.*?),(.*)$", REG_EXTENDED|REG_NOSUB);
01533 regcomp(&fapint_regex_detect_exp, "^\\{\\{", REG_EXTENDED|REG_NOSUB);
01534
01535 regcomp(&fapint_regex_kiss_hdrbdy, "^([A-Z0-9,*>-]+):(.+)$", REG_EXTENDED);
01536 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);
01537 regcomp(&fapint_regex_kiss_digi, "^([A-Z0-9]{1,6})(-[0-9]{1,2})?(\\*)?$", REG_EXTENDED);
01538
01539 regcomp(&fapint_regex_hopcount1, "^([A-Z0-9-]+)\\*$", REG_EXTENDED);
01540 regcomp(&fapint_regex_hopcount2, "^WIDE([1-7])-([0-7])$", REG_EXTENDED);
01541
01542
01543
01544 fapint_initialized = 1;
01545 }
01546 }
01547
01548
01549
01550 void fap_cleanup()
01551 {
01552 if ( fapint_initialized )
01553 {
01554
01555 regfree(&fapint_regex_header);
01556 regfree(&fapint_regex_ax25call);
01557 regfree(&fapint_regex_digicall);
01558
01559 regfree(&fapint_regex_normalpos);
01560 regfree(&fapint_regex_normalamb);
01561 regfree(&fapint_regex_timestamp);
01562
01563 regfree(&fapint_regex_mice_dstcall);
01564 regfree(&fapint_regex_mice_body);
01565 regfree(&fapint_regex_mice_amb);
01566
01567 regfree(&fapint_regex_comment);
01568 regfree(&fapint_regex_phgr);
01569 regfree(&fapint_regex_phg);
01570 regfree(&fapint_regex_rng);
01571 regfree(&fapint_regex_altitude);
01572
01573 regfree(&fapint_regex_mes_dst);
01574 regfree(&fapint_regex_mes_ack);
01575 regfree(&fapint_regex_mes_nack);
01576
01577 regfree(&fapint_regex_wx1);
01578 regfree(&fapint_regex_wx2);
01579 regfree(&fapint_regex_wx3);
01580 regfree(&fapint_regex_wx4);
01581 regfree(&fapint_regex_wx5);
01582
01583 regfree(&fapint_regex_wx_r1);
01584 regfree(&fapint_regex_wx_r24);
01585 regfree(&fapint_regex_wx_rami);
01586
01587 regfree(&fapint_regex_wx_humi);
01588 regfree(&fapint_regex_wx_pres);
01589 regfree(&fapint_regex_wx_lumi);
01590 regfree(&fapint_regex_wx_what);
01591 regfree(&fapint_regex_wx_snow);
01592 regfree(&fapint_regex_wx_rrc);
01593 regfree(&fapint_regex_wx_any);
01594
01595 regfree(&fapint_regex_nmea_chksum);
01596 regfree(&fapint_regex_nmea_dst);
01597 regfree(&fapint_regex_nmea_time);
01598 regfree(&fapint_regex_nmea_date);
01599
01600 regfree(&fapint_regex_nmea_specou);
01601 regfree(&fapint_regex_nmea_fix);
01602 regfree(&fapint_regex_nmea_altitude);
01603 regfree(&fapint_regex_nmea_flag);
01604 regfree(&fapint_regex_nmea_coord);
01605
01606 regfree(&fapint_regex_telemetry);
01607 regfree(&fapint_regex_peet_splitter);
01608 regfree(&fapint_regex_kiss_callsign);
01609
01610 regfree(&fapint_regex_detect_comp);
01611 regfree(&fapint_regex_detect_wx);
01612 regfree(&fapint_regex_detect_telem);
01613 regfree(&fapint_regex_detect_exp);
01614
01615 regfree(&fapint_regex_kiss_hdrbdy);
01616 regfree(&fapint_regex_hdr_detail);
01617 regfree(&fapint_regex_kiss_digi);
01618
01619 regfree(&fapint_regex_hopcount1);
01620 regfree(&fapint_regex_hopcount2);
01621
01622
01623 fapint_initialized = 0;
01624 }
01625 }
01626
01627
01628
01629 void fap_free(fap_packet_t* packet)
01630 {
01631 unsigned int i;
01632
01633 if ( packet == NULL )
01634 {
01635 return;
01636 }
01637
01638 if ( packet->error_code ) { free(packet->error_code); }
01639 if ( packet->error_message ) { free(packet->error_message); }
01640 if ( packet->type ) { free(packet->type); }
01641
01642 if ( packet->orig_packet ) { free(packet->orig_packet); }
01643
01644 if ( packet->header ) { free(packet->header); }
01645 if ( packet->body ) { free(packet->body); }
01646 if ( packet->src_callsign ) { free(packet->src_callsign); }
01647 if ( packet->dst_callsign ) { free(packet->dst_callsign); }
01648 for ( i = 0; i < packet->path_len; ++i )
01649 {
01650 if ( packet->path[i] ) { free(packet->path[i]); }
01651 }
01652 if ( packet->path ) { free(packet->path); }
01653
01654 if ( packet->latitude ) { free(packet->latitude); }
01655 if ( packet->longitude ) { free(packet->longitude); }
01656 if ( packet->pos_resolution ) { free(packet->pos_resolution); }
01657 if ( packet->pos_ambiguity ) { free(packet->pos_ambiguity); }
01658
01659 if ( packet->altitude ) { free(packet->altitude); }
01660 if ( packet->course ) { free(packet->course); }
01661 if ( packet->speed ) { free(packet->speed); }
01662
01663 if ( packet->messaging ) { free(packet->messaging); }
01664 if ( packet->destination ) { free(packet->destination); }
01665 if ( packet->message ) { free(packet->message); }
01666 if ( packet->message_ack ) { free(packet->message_ack); }
01667 if ( packet->message_nack ) { free(packet->message_nack); }
01668 if ( packet->message_id ) { free(packet->message_id); }
01669 if ( packet->comment ) { free(packet->comment); }
01670
01671 if ( packet->object_or_item_name ) { free(packet->object_or_item_name); }
01672 if ( packet->alive ) { free(packet->alive); }
01673
01674 if ( packet->gps_fix_status ) { free(packet->gps_fix_status); }
01675 if ( packet->radio_range ) { free(packet->radio_range); }
01676 if ( packet->phg ) { free(packet->phg); }
01677 if ( packet->timestamp ) { free(packet->timestamp); }
01678 if ( packet->nmea_checksum_ok ) { free(packet->nmea_checksum_ok); }
01679
01680 if ( packet->wx_report )
01681 {
01682 if ( packet->wx_report->wind_gust ) { free(packet->wx_report->wind_gust); }
01683 if ( packet->wx_report->wind_dir ) { free(packet->wx_report->wind_dir); }
01684 if ( packet->wx_report->wind_speed ) { free(packet->wx_report->wind_speed); }
01685
01686 if ( packet->wx_report->temp ) { free(packet->wx_report->temp); }
01687 if ( packet->wx_report->temp_in ) { free(packet->wx_report->temp_in); }
01688
01689 if ( packet->wx_report->rain_1h ) { free(packet->wx_report->rain_1h); }
01690 if ( packet->wx_report->rain_24h ) { free(packet->wx_report->rain_24h); }
01691 if ( packet->wx_report->rain_midnight ) { free(packet->wx_report->rain_midnight); }
01692
01693 if ( packet->wx_report->humidity ) { free(packet->wx_report->humidity); }
01694 if ( packet->wx_report->humidity_in ) { free(packet->wx_report->humidity_in); }
01695
01696 if ( packet->wx_report->pressure ) { free(packet->wx_report->pressure); }
01697 if ( packet->wx_report->luminosity ) { free(packet->wx_report->luminosity); }
01698
01699 if ( packet->wx_report->snow_24h ) { free(packet->wx_report->snow_24h); }
01700
01701 if ( packet->wx_report->soft ) { free(packet->wx_report->soft); }
01702
01703 free(packet->wx_report);
01704 }
01705
01706 if ( packet->telemetry ) { free(packet->telemetry); }
01707
01708 if ( packet->messagebits ) { free(packet->messagebits); }
01709 if ( packet->status ) { free(packet->status); }
01710 for ( i = 0; i < packet->capabilities_len*2; i += 2 )
01711 {
01712 if ( packet->capabilities[i] ) { free(packet->capabilities[i]); }
01713 if ( packet->capabilities[i+1] ) { free(packet->capabilities[i+1]); }
01714 }
01715 if ( packet->capabilities ) { free(packet->capabilities); }
01716
01717 free(packet);
01718 }