88import java .util .*;
99import java .util .regex .*;
1010import java .math .BigInteger ;
11+ import java .nio .ByteBuffer ;
1112import java .nio .MappedByteBuffer ;
1213import java .nio .ByteOrder ;
1314import java .nio .channels .FileChannel ;
@@ -114,7 +115,7 @@ private enum Modes {
114115 private boolean AS_ENABLED ;
115116 private boolean LASTSEEN_ENABLED ;
116117
117- private static final String _ModuleVersion = "2.1 .0" ;
118+ private static final String _ModuleVersion = "2.2 .0" ;
118119
119120 public IP2Proxy () {
120121
@@ -372,16 +373,29 @@ private boolean LoadBIN() throws IOException {
372373 _IPv6ColumnSize = 16 + ((_DBColumn - 1 ) << 2 ); // 4 bytes each column, except IPFrom column which is 16 bytes
373374
374375 // since both IPv4 and IPv6 use 4 bytes for the below columns, can just do it once here
375- COUNTRY_POSITION_OFFSET = (COUNTRY_POSITION [_DBType ] != 0 ) ? (COUNTRY_POSITION [_DBType ] - 1 ) << 2 : 0 ;
376- REGION_POSITION_OFFSET = (REGION_POSITION [_DBType ] != 0 ) ? (REGION_POSITION [_DBType ] - 1 ) << 2 : 0 ;
377- CITY_POSITION_OFFSET = (CITY_POSITION [_DBType ] != 0 ) ? (CITY_POSITION [_DBType ] - 1 ) << 2 : 0 ;
378- ISP_POSITION_OFFSET = (ISP_POSITION [_DBType ] != 0 ) ? (ISP_POSITION [_DBType ] - 1 ) << 2 : 0 ;
379- PROXYTYPE_POSITION_OFFSET = (PROXYTYPE_POSITION [_DBType ] != 0 ) ? (PROXYTYPE_POSITION [_DBType ] - 1 ) << 2 : 0 ;
380- DOMAIN_POSITION_OFFSET = (DOMAIN_POSITION [_DBType ] != 0 ) ? (DOMAIN_POSITION [_DBType ] - 1 ) << 2 : 0 ;
381- USAGETYPE_POSITION_OFFSET = (USAGETYPE_POSITION [_DBType ] != 0 ) ? (USAGETYPE_POSITION [_DBType ] - 1 ) << 2 : 0 ;
382- ASN_POSITION_OFFSET = (ASN_POSITION [_DBType ] != 0 ) ? (ASN_POSITION [_DBType ] - 1 ) << 2 : 0 ;
383- AS_POSITION_OFFSET = (AS_POSITION [_DBType ] != 0 ) ? (AS_POSITION [_DBType ] - 1 ) << 2 : 0 ;
384- LASTSEEN_POSITION_OFFSET = (LASTSEEN_POSITION [_DBType ] != 0 ) ? (LASTSEEN_POSITION [_DBType ] - 1 ) << 2 : 0 ;
376+ // COUNTRY_POSITION_OFFSET = (COUNTRY_POSITION[_DBType] != 0) ? (COUNTRY_POSITION[_DBType] - 1) << 2 : 0;
377+ // REGION_POSITION_OFFSET = (REGION_POSITION[_DBType] != 0) ? (REGION_POSITION[_DBType] - 1) << 2 : 0;
378+ // CITY_POSITION_OFFSET = (CITY_POSITION[_DBType] != 0) ? (CITY_POSITION[_DBType] - 1) << 2 : 0;
379+ // ISP_POSITION_OFFSET = (ISP_POSITION[_DBType] != 0) ? (ISP_POSITION[_DBType] - 1) << 2 : 0;
380+ // PROXYTYPE_POSITION_OFFSET = (PROXYTYPE_POSITION[_DBType] != 0) ? (PROXYTYPE_POSITION[_DBType] - 1) << 2 : 0;
381+ // DOMAIN_POSITION_OFFSET = (DOMAIN_POSITION[_DBType] != 0) ? (DOMAIN_POSITION[_DBType] - 1) << 2 : 0;
382+ // USAGETYPE_POSITION_OFFSET = (USAGETYPE_POSITION[_DBType] != 0) ? (USAGETYPE_POSITION[_DBType] - 1) << 2 : 0;
383+ // ASN_POSITION_OFFSET = (ASN_POSITION[_DBType] != 0) ? (ASN_POSITION[_DBType] - 1) << 2 : 0;
384+ // AS_POSITION_OFFSET = (AS_POSITION[_DBType] != 0) ? (AS_POSITION[_DBType] - 1) << 2 : 0;
385+ // LASTSEEN_POSITION_OFFSET = (LASTSEEN_POSITION[_DBType] != 0) ? (LASTSEEN_POSITION[_DBType] - 1) << 2 : 0;
386+
387+ // slightly different offset for reading by row
388+ COUNTRY_POSITION_OFFSET = (COUNTRY_POSITION [_DBType ] != 0 ) ? (COUNTRY_POSITION [_DBType ] - 2 ) << 2 : 0 ;
389+ REGION_POSITION_OFFSET = (REGION_POSITION [_DBType ] != 0 ) ? (REGION_POSITION [_DBType ] - 2 ) << 2 : 0 ;
390+ CITY_POSITION_OFFSET = (CITY_POSITION [_DBType ] != 0 ) ? (CITY_POSITION [_DBType ] - 2 ) << 2 : 0 ;
391+ ISP_POSITION_OFFSET = (ISP_POSITION [_DBType ] != 0 ) ? (ISP_POSITION [_DBType ] - 2 ) << 2 : 0 ;
392+ PROXYTYPE_POSITION_OFFSET = (PROXYTYPE_POSITION [_DBType ] != 0 ) ? (PROXYTYPE_POSITION [_DBType ] - 2 ) << 2 : 0 ;
393+ DOMAIN_POSITION_OFFSET = (DOMAIN_POSITION [_DBType ] != 0 ) ? (DOMAIN_POSITION [_DBType ] - 2 ) << 2 : 0 ;
394+ USAGETYPE_POSITION_OFFSET = (USAGETYPE_POSITION [_DBType ] != 0 ) ? (USAGETYPE_POSITION [_DBType ] - 2 ) << 2 : 0 ;
395+ ASN_POSITION_OFFSET = (ASN_POSITION [_DBType ] != 0 ) ? (ASN_POSITION [_DBType ] - 2 ) << 2 : 0 ;
396+ AS_POSITION_OFFSET = (AS_POSITION [_DBType ] != 0 ) ? (AS_POSITION [_DBType ] - 2 ) << 2 : 0 ;
397+ LASTSEEN_POSITION_OFFSET = (LASTSEEN_POSITION [_DBType ] != 0 ) ? (LASTSEEN_POSITION [_DBType ] - 2 ) << 2 : 0 ;
398+
385399
386400 COUNTRY_ENABLED = (COUNTRY_POSITION [_DBType ] != 0 ) ? true : false ;
387401 REGION_ENABLED = (REGION_POSITION [_DBType ] != 0 ) ? true : false ;
@@ -477,7 +491,9 @@ public ProxyResult ProxyQuery(String IPAddress) throws IOException {
477491 public ProxyResult ProxyQuery (String IPAddress , Modes Mode ) throws IOException {
478492 ProxyResult Result = new ProxyResult ();
479493 RandomAccessFile RF = null ;
480- MappedByteBuffer Buf = null ;
494+ // MappedByteBuffer Buf = null;
495+ ByteBuffer Buf = null ;
496+ ByteBuffer DataBuf = null ;
481497
482498 try {
483499 if (IPAddress == null || IPAddress .length () == 0 ) {
@@ -538,7 +554,7 @@ public ProxyResult ProxyQuery(String IPAddress, Modes Mode) throws IOException {
538554 return Result ;
539555 }
540556
541- long CountryPos = 0 ;
557+ long Pos = 0 ;
542558 long Low = 0 ;
543559 long High = 0 ;
544560 long Mid = 0 ;
@@ -579,7 +595,9 @@ public ProxyResult ProxyQuery(String IPAddress, Modes Mode) throws IOException {
579595 High = _DBCount ;
580596
581597 if (_UseMemoryMappedFile ) {
582- Buf = _IPv4Buffer ;
598+ // Buf = _IPv4Buffer;
599+ Buf = _IPv4Buffer .duplicate (); // this enables this thread to maintain its own position in a multi-threaded environment
600+ Buf .order (ByteOrder .LITTLE_ENDIAN );
583601 BufCapacity = Buf .capacity ();
584602 }
585603 else {
@@ -611,7 +629,9 @@ public ProxyResult ProxyQuery(String IPAddress, Modes Mode) throws IOException {
611629 High = _DBCountIPv6 ;
612630
613631 if (_UseMemoryMappedFile ) {
614- Buf = _IPv6Buffer ;
632+ // Buf = _IPv6Buffer;
633+ Buf = _IPv6Buffer .duplicate (); // this enables this thread to maintain its own position in a multi-threaded environment
634+ Buf .order (ByteOrder .LITTLE_ENDIAN );
615635 BufCapacity = Buf .capacity ();
616636 }
617637 else {
@@ -654,73 +674,97 @@ public ProxyResult ProxyQuery(String IPAddress, Modes Mode) throws IOException {
654674 String AS = MSG_NOT_SUPPORTED ;
655675 String Last_Seen = MSG_NOT_SUPPORTED ;
656676
677+ int FirstCol = 4 ; // IP From is 4 bytes
657678 if (IPType == 6 ) { // IPv6
658- RowOffset = RowOffset + 12 ; // coz below is assuming all columns are 4 bytes, so got 12 left to go to make 16 bytes total
679+ FirstCol = 16 ; // IPv6 is 16 bytes
680+ // RowOffset = RowOffset + 12; // coz below is assuming all columns are 4 bytes, so got 12 left to go to make 16 bytes total
681+ }
682+
683+ // read the row here after the IP From column (remaining columns are all 4 bytes)
684+ int RowLen = ColumnSize - FirstCol ;
685+ byte [] Row ;
686+ Row = ReadRow (RowOffset + FirstCol , RowLen , Buf , RF );
687+
688+ if (_UseMemoryMappedFile ) {
689+ DataBuf = _MapDataBuffer .duplicate (); // this is to enable reading of a range of bytes in multi-threaded environment
690+ DataBuf .order (ByteOrder .LITTLE_ENDIAN );
659691 }
660692
661693 if (PROXYTYPE_ENABLED ) {
662694 if (Mode == Modes .ALL || Mode == Modes .PROXY_TYPE || Mode == Modes .IS_PROXY ) {
663- Proxy_Type = ReadStr (Read32 (RowOffset + PROXYTYPE_POSITION_OFFSET , Buf , RF ).longValue (), RF );
695+ // Proxy_Type = ReadStr(Read32(RowOffset + PROXYTYPE_POSITION_OFFSET, Buf, RF).longValue(), RF);
696+ Proxy_Type = ReadStr (Read32_Row (Row , PROXYTYPE_POSITION_OFFSET ).longValue (), DataBuf , RF );
664697 }
665698 }
666699
667700 if (COUNTRY_ENABLED ) {
668701 if (Mode == Modes .ALL || Mode == Modes .COUNTRY_SHORT || Mode == Modes .COUNTRY_LONG || Mode == Modes .IS_PROXY ) {
669- CountryPos = Read32 (RowOffset + COUNTRY_POSITION_OFFSET , Buf , RF ).longValue ();
702+ // CountryPos = Read32(RowOffset + COUNTRY_POSITION_OFFSET, Buf, RF).longValue();
703+ Pos = Read32_Row (Row , COUNTRY_POSITION_OFFSET ).longValue ();
670704 }
671705 if (Mode == Modes .ALL || Mode == Modes .COUNTRY_SHORT || Mode == Modes .IS_PROXY ) {
672- Country_Short = ReadStr (CountryPos , RF );
706+ // Country_Short = ReadStr(CountryPos, RF);
707+ Country_Short = ReadStr (Pos , DataBuf , RF );
673708 }
674709 if (Mode == Modes .ALL || Mode == Modes .COUNTRY_LONG ) {
675- Country_Long = ReadStr (CountryPos + 3 , RF );
710+ // Country_Long = ReadStr(CountryPos + 3, RF);
711+ Country_Long = ReadStr (Pos + 3 , DataBuf , RF );
676712 }
677713 }
678714
679715 if (REGION_ENABLED ) {
680716 if (Mode == Modes .ALL || Mode == Modes .REGION ) {
681- Region = ReadStr (Read32 (RowOffset + REGION_POSITION_OFFSET , Buf , RF ).longValue (), RF );
717+ // Region = ReadStr(Read32(RowOffset + REGION_POSITION_OFFSET, Buf, RF).longValue(), RF);
718+ Region = ReadStr (Read32_Row (Row , REGION_POSITION_OFFSET ).longValue (), DataBuf , RF );
682719 }
683720 }
684721
685722 if (CITY_ENABLED ) {
686723 if (Mode == Modes .ALL || Mode == Modes .CITY ) {
687- City = ReadStr (Read32 (RowOffset + CITY_POSITION_OFFSET , Buf , RF ).longValue (), RF );
724+ // City = ReadStr(Read32(RowOffset + CITY_POSITION_OFFSET, Buf, RF).longValue(), RF);
725+ City = ReadStr (Read32_Row (Row , CITY_POSITION_OFFSET ).longValue (), DataBuf , RF );
688726 }
689727 }
690728
691729 if (ISP_ENABLED ) {
692730 if (Mode == Modes .ALL || Mode == Modes .ISP ) {
693- ISP = ReadStr (Read32 (RowOffset + ISP_POSITION_OFFSET , Buf , RF ).longValue (), RF );
731+ // ISP = ReadStr(Read32(RowOffset + ISP_POSITION_OFFSET, Buf, RF).longValue(), RF);
732+ ISP = ReadStr (Read32_Row (Row , ISP_POSITION_OFFSET ).longValue (), DataBuf , RF );
694733 }
695734 }
696735
697736 if (DOMAIN_ENABLED ) {
698737 if (Mode == Modes .ALL || Mode == Modes .DOMAIN ) {
699- Domain = ReadStr (Read32 (RowOffset + DOMAIN_POSITION_OFFSET , Buf , RF ).longValue (), RF );
738+ // Domain = ReadStr(Read32(RowOffset + DOMAIN_POSITION_OFFSET, Buf, RF).longValue(), RF);
739+ Domain = ReadStr (Read32_Row (Row , DOMAIN_POSITION_OFFSET ).longValue (), DataBuf , RF );
700740 }
701741 }
702742
703743 if (USAGETYPE_ENABLED ) {
704744 if (Mode == Modes .ALL || Mode == Modes .USAGE_TYPE ) {
705- Usage_Type = ReadStr (Read32 (RowOffset + USAGETYPE_POSITION_OFFSET , Buf , RF ).longValue (), RF );
745+ // Usage_Type = ReadStr(Read32(RowOffset + USAGETYPE_POSITION_OFFSET, Buf, RF).longValue(), RF);
746+ Usage_Type = ReadStr (Read32_Row (Row , USAGETYPE_POSITION_OFFSET ).longValue (), DataBuf , RF );
706747 }
707748 }
708749
709750 if (ASN_ENABLED ) {
710751 if (Mode == Modes .ALL || Mode == Modes .ASN ) {
711- ASN = ReadStr (Read32 (RowOffset + ASN_POSITION_OFFSET , Buf , RF ).longValue (), RF );
752+ // ASN = ReadStr(Read32(RowOffset + ASN_POSITION_OFFSET, Buf, RF).longValue(), RF);
753+ ASN = ReadStr (Read32_Row (Row , ASN_POSITION_OFFSET ).longValue (), DataBuf , RF );
712754 }
713755 }
714756
715757 if (AS_ENABLED ) {
716758 if (Mode == Modes .ALL || Mode == Modes .AS ) {
717- AS = ReadStr (Read32 (RowOffset + AS_POSITION_OFFSET , Buf , RF ).longValue (), RF );
759+ // AS = ReadStr(Read32(RowOffset + AS_POSITION_OFFSET, Buf, RF).longValue(), RF);
760+ AS = ReadStr (Read32_Row (Row , AS_POSITION_OFFSET ).longValue (), DataBuf , RF );
718761 }
719762 }
720763
721764 if (LASTSEEN_ENABLED ) {
722765 if (Mode == Modes .ALL || Mode == Modes .LAST_SEEN ) {
723- Last_Seen = ReadStr (Read32 (RowOffset + LASTSEEN_POSITION_OFFSET , Buf , RF ).longValue (), RF );
766+ // Last_Seen = ReadStr(Read32(RowOffset + LASTSEEN_POSITION_OFFSET, Buf, RF).longValue(), RF);
767+ Last_Seen = ReadStr (Read32_Row (Row , LASTSEEN_POSITION_OFFSET ).longValue (), DataBuf , RF );
724768 }
725769 }
726770
@@ -1011,7 +1055,20 @@ private void Reverse(byte[] Arr) {
10111055 }
10121056 }
10131057
1014- private BigInteger Read32Or128 (final long Position , final int IPType , final MappedByteBuffer Buf , final RandomAccessFile RH ) throws IOException {
1058+ private byte [] ReadRow (final long Position , final long MyLen , final ByteBuffer Buf , final RandomAccessFile RH ) throws IOException {
1059+ byte [] Row = new byte [(int )MyLen ];
1060+ if (_UseMemoryMappedFile ) {
1061+ Buf .position ((int )Position );
1062+ Buf .get (Row , (int )0 , (int )MyLen );
1063+ }
1064+ else {
1065+ RH .seek (Position - 1 );
1066+ RH .read (Row , (int )0 , (int )MyLen );
1067+ }
1068+ return Row ;
1069+ }
1070+
1071+ private BigInteger Read32Or128 (final long Position , final int IPType , final ByteBuffer Buf , final RandomAccessFile RH ) throws IOException {
10151072 if (IPType == 4 ) {
10161073 return Read32 (Position , Buf , RH );
10171074 }
@@ -1021,28 +1078,33 @@ else if (IPType == 6) {
10211078 return BigInteger .ZERO ;
10221079 }
10231080
1024- private BigInteger Read128 (final long Position , final MappedByteBuffer Buf , final RandomAccessFile RH ) throws IOException {
1081+ private BigInteger Read128 (final long Position , final ByteBuffer Buf , final RandomAccessFile RH ) throws IOException {
10251082 BigInteger RetVal = BigInteger .ZERO ;
10261083 final int BSize = 16 ;
10271084 byte Bytes [] = new byte [BSize ];
10281085
10291086 if (_UseMemoryMappedFile ) {
1030- for (int x = 0 ; x < BSize ; x ++) {
1031- Bytes [x ] = Buf .get ((int )Position + x ); // use absolute offset to be thread-safe
1032- }
1087+ Buf .position ((int )Position );
1088+ Buf .get (Bytes , (int )0 , BSize );
10331089 }
10341090 else {
10351091 RH .seek (Position - 1 );
1036- for (int x = 0 ; x < BSize ; x ++) {
1037- Bytes [x ] = RH .readByte ();
1038- }
1092+ RH .read (Bytes , (int )0 , BSize );
10391093 }
10401094 Reverse (Bytes );
10411095 RetVal = new BigInteger (1 , Bytes );
10421096 return RetVal ;
10431097 }
1044-
1045- private BigInteger Read32 (final long Position , final MappedByteBuffer Buf , final RandomAccessFile RH ) throws IOException {
1098+
1099+ private BigInteger Read32_Row (byte [] Row , final int From ) throws IOException {
1100+ final int Len = 4 ; // 4 bytes
1101+ byte Bytes [] = new byte [Len ];
1102+ System .arraycopy (Row , From , Bytes , (int )0 , Len );
1103+ Reverse (Bytes );
1104+ return new BigInteger (1 , Bytes );
1105+ }
1106+
1107+ private BigInteger Read32 (final long Position , final ByteBuffer Buf , final RandomAccessFile RH ) throws IOException {
10461108 if (_UseMemoryMappedFile ) {
10471109 // simulate unsigned int by using long
10481110 return BigInteger .valueOf (Buf .getInt ((int )Position ) & 0xffffffffL ); // use absolute offset to be thread-safe
@@ -1051,27 +1113,24 @@ private BigInteger Read32(final long Position, final MappedByteBuffer Buf, final
10511113 final int BSize = 4 ;
10521114 RH .seek (Position - 1 );
10531115 byte Bytes [] = new byte [BSize ];
1054- for (int x = 0 ; x < BSize ; x ++) {
1055- Bytes [x ] = RH .readByte ();
1056- }
1116+ RH .read (Bytes , (int )0 , BSize );
10571117 Reverse (Bytes );
10581118 return new BigInteger (1 , Bytes );
10591119 }
10601120 }
1061-
1062- private String ReadStr (long Position , final RandomAccessFile RH ) throws IOException {
1121+
1122+ private String ReadStr (long Position , final ByteBuffer Buf , final RandomAccessFile RH ) throws IOException {
10631123 final int Size ;
1064- char CBuf [] = null ;
1124+ byte [] Bytes = null ;
10651125
10661126 if (_UseMemoryMappedFile ) {
10671127 Position = Position - _MapDataOffset ; // position stored in BIN file is for full file, not just the mapped data segment, so need to minus
10681128 Size = _MapDataBuffer .get ((int )Position ); // use absolute offset to be thread-safe
10691129
10701130 try {
1071- CBuf = new char [Size ];
1072- for (int x = 0 ; x < Size ; x ++) {
1073- CBuf [x ] = (char )_MapDataBuffer .get ((int )Position + 1 + x ); // use absolute offset to be thread-safe
1074- }
1131+ Bytes = new byte [Size ];
1132+ Buf .position ((int )Position + 1 );
1133+ Buf .get (Bytes , (int )0 , Size );
10751134 }
10761135 catch (NegativeArraySizeException e ) {
10771136 return null ;
@@ -1081,16 +1140,16 @@ private String ReadStr(long Position, final RandomAccessFile RH) throws IOExcept
10811140 RH .seek (Position );
10821141 Size = RH .read ();
10831142 try {
1084- CBuf = new char [Size ];
1085- for (int x = 0 ; x < Size ; x ++) {
1086- CBuf [x ] = (char )RH .read ();
1087- }
1143+ Bytes = new byte [Size ];
1144+ RH .read (Bytes , (int )0 , Size );
10881145 }
10891146 catch (NegativeArraySizeException e ) {
10901147 return null ;
10911148 }
10921149 }
1093- return String .copyValueOf (CBuf );
1150+
1151+ String S = new String (Bytes );
1152+ return S ;
10941153 }
10951154
10961155 private BigInteger [] IP2No (String IP ) throws UnknownHostException {
@@ -1125,12 +1184,14 @@ else if (IA instanceof Inet4Address) { // this will run in cases of IPv4-mapped
11251184 IPType = "4" ;
11261185 A2 = A2 .shiftRight (80 );
11271186 A2 = A2 .and (LAST_32BITS );
1187+ A3 = new BigInteger ("4" );
11281188 }
11291189 else if (A2 .compareTo (FROM_TEREDO ) >= 0 && A2 .compareTo (TO_TEREDO ) <= 0 ) {
11301190 // Teredo so need to remap to ipv4
11311191 IPType = "4" ;
11321192 A2 = A2 .not ();
11331193 A2 = A2 .and (LAST_32BITS );
1194+ A3 = new BigInteger ("4" );
11341195 }
11351196 A1 = new BigInteger (IPType );
11361197 }
0 commit comments