1 /*
2  * Created on Mar 7, 2012
3  * Created by Paul Gardner
4  *
5  * Copyright (C) Azureus Software, Inc, All Rights Reserved.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  */
19 
20 
21 package com.aelitis.azureus.core.peermanager.messaging.azureus;
22 
23 import java.nio.ByteBuffer;
24 import java.util.HashMap;
25 import java.util.Map;
26 
27 import org.gudy.azureus2.core3.util.BDecoder;
28 import org.gudy.azureus2.core3.util.BEncoder;
29 import org.gudy.azureus2.core3.util.DirectByteBuffer;
30 
31 import com.aelitis.azureus.core.peermanager.messaging.Message;
32 import com.aelitis.azureus.core.peermanager.messaging.MessageException;
33 import com.aelitis.azureus.core.peermanager.messaging.MessagingUtil;
34 
35 public class
36 AZMetaData
37 	implements AZMessage, AZUTMetaData
38 {
39 	private final byte version;
40 	private DirectByteBuffer buffer = null;
41 
42 	private int					msg_type;
43 	private int					piece;
44 	private DirectByteBuffer	metadata;
45 	private int					total_size;
46 
47 	public
AZMetaData( int _piece, byte _version )48 	AZMetaData(
49 		int		_piece,
50 		byte	_version )
51 	{
52 		msg_type	= MSG_TYPE_REQUEST;
53 		piece		= _piece;
54 		version		= _version;
55 	}
56 
57 	public
AZMetaData( int _piece, ByteBuffer _data, int _total_size, byte _version )58 	AZMetaData(
59 		int				_piece,
60 		ByteBuffer		_data,
61 		int				_total_size,
62 		byte			_version )
63 	{
64 		msg_type	= _data==null?MSG_TYPE_REJECT:MSG_TYPE_DATA;
65 		piece		= _piece;
66 		total_size	= _total_size;
67 		version		= _version;
68 
69 		if ( _data != null ){
70 
71 			metadata = new DirectByteBuffer( _data );
72 		}
73 	}
74 
75 	public
AZMetaData( Map map, DirectByteBuffer data, byte _version )76 	AZMetaData(
77 		Map					map,
78 		DirectByteBuffer	data,
79 		byte				_version )
80 	{
81 		if ( map != null ){
82 
83 			msg_type = ((Long)map.get( "msg_type" )).intValue();
84 			piece	 = ((Long)map.get( "piece" )).intValue();
85 		}
86 
87 		metadata	= data;
88 		version		= _version;
89 	}
90 
91 	public String
getID()92 	getID()
93 	{
94 		return( ID_AZ_METADATA );
95 	}
96 
97 	public byte[]
getIDBytes()98 	getIDBytes()
99 	{
100 		return( ID_AZ_METADATA_BYTES );
101 	}
102 
103 	public String
getFeatureID()104 	getFeatureID()
105 	{
106 		return( AZ_FEATURE_ID );
107 	}
108 
109 	public int
getFeatureSubID()110 	getFeatureSubID()
111 	{
112 		return SUBID_ID_AZ_METADATA;
113 	}
114 
115 	public int
getType()116 	getType()
117 	{
118 		return Message.TYPE_PROTOCOL_PAYLOAD;
119 	}
120 
121 	public byte
getVersion()122 	getVersion()
123 	{
124 		return( version );
125 	};
126 
127 	public String
getDescription()128 	getDescription()
129 	{
130 		return( getID() + " piece #" + piece + ", mt=" + msg_type );
131 	}
132 
133 	public int
getMessageType()134 	getMessageType()
135 	{
136 		return( msg_type );
137 	}
138 
139 	public int
getPiece()140 	getPiece()
141 	{
142 		return( piece );
143 	}
144 
145 	public DirectByteBuffer
getMetadata()146 	getMetadata()
147 	{
148 		return( metadata );
149 	}
150 
151 	public void
setMetadata( DirectByteBuffer b )152 	setMetadata(
153 		DirectByteBuffer	b )
154 	{
155 		metadata = b;
156 	}
157 
158 	public DirectByteBuffer[]
getData()159 	getData()
160 	{
161 		if ( buffer == null ){
162 
163 			Map payload_map = new HashMap();
164 
165 			payload_map.put( "msg_type", new Long( msg_type ));
166 			payload_map.put( "piece", new Long(piece));
167 
168 			if ( total_size > 0 ){
169 
170 				payload_map.put( "total_size", total_size );
171 			}
172 
173 			buffer = MessagingUtil.convertPayloadToBencodedByteStream(payload_map, DirectByteBuffer.AL_MSG_AZ_METADATA );
174 		}
175 
176 		if ( msg_type == MSG_TYPE_DATA ){
177 
178 			return new DirectByteBuffer[]{ buffer, metadata };
179 
180 		}else{
181 
182 			return new DirectByteBuffer[]{ buffer };
183 		}
184 	}
185 
186 
187 
188 	public Message
deserialize( DirectByteBuffer data, byte version )189 	deserialize(
190 		DirectByteBuffer 	data,
191 		byte 				version )
192 
193 		throws MessageException
194 	{
195 		int	pos = data.position( DirectByteBuffer.SS_MSG );
196 
197 		byte[] dict_bytes = new byte[ Math.min( 128, data.remaining( DirectByteBuffer.SS_MSG )) ];
198 
199 		data.get( DirectByteBuffer.SS_MSG, dict_bytes );
200 
201 		try{
202 			Map root = BDecoder.decode( dict_bytes );
203 
204 			data.position( DirectByteBuffer.SS_MSG, pos + BEncoder.encode( root ).length );
205 
206 			return( new AZMetaData( root, data, version ));
207 
208 		}catch( Throwable e ){
209 
210 			e.printStackTrace();
211 
212 			throw( new MessageException( "decode failed", e ));
213 		}
214 	}
215 
216 
217 	public void
destroy()218 	destroy()
219 	{
220 		if ( buffer != null ){
221 
222 			buffer.returnToPool();
223 		}
224 
225 		if ( metadata != null ){
226 
227 			metadata.returnToPool();
228 		}
229 	}
230 }