summaryrefslogtreecommitdiffstats
path: root/src/main/java/org/openslx/satellitedaemon/filetransfer/ThriftConnection.java
blob: 673be05dbc4b8755eada23d6b5331ef5f984930c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
package org.openslx.satellitedaemon.filetransfer;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
import org.openslx.encryption.AsymEncryptionHandler;
import org.openslx.imagemaster.crcchecker.CrcFile;
import org.openslx.imagemaster.thrift.iface.AuthorizationError;
import org.openslx.imagemaster.thrift.iface.AuthorizationException;
import org.openslx.imagemaster.thrift.iface.DownloadData;
import org.openslx.imagemaster.thrift.iface.ImageData;
import org.openslx.imagemaster.thrift.iface.ImageDataError;
import org.openslx.imagemaster.thrift.iface.ImageDataException;
import org.openslx.imagemaster.thrift.iface.ImageServer;
import org.openslx.imagemaster.thrift.iface.ServerAuthenticationException;
import org.openslx.imagemaster.thrift.iface.ServerSessionData;
import org.openslx.imagemaster.thrift.iface.UploadError;
import org.openslx.imagemaster.thrift.iface.UploadException;
import org.openslx.imagemaster.thrift.iface.UploadData;
import org.openslx.satellitedaemon.Globals;
import org.openslx.satellitedaemon.db.DbImage;
import org.openslx.satellitedaemon.db.DbImage.Status;
import org.openslx.satellitedaemon.util.EncryptWithServerIdPublicKey;

// TODO: Handle all the auto-generated catch blocks in a meaningful way

/***********************************************************************************************/
/**
 * Handles the authentication with the Satellite Server and sends the
 * FILTRANSFERCredentials, which are necessary for the upload of the image.
 */
public class ThriftConnection {
	private static ImageServer.Client client = null;
	private static ServerSessionData sSD = null;
	private static Logger log = Logger.getLogger(ThriftConnection.class);
	private static CrcFile crc = null;
	

	/***********************************************************************************************/
	/**
	 * Method for getting UploadeInfos
	 * 
	 * when the CRCsum need to be transfered. The method calls getConnection()
	 * to check if the connection is ok and to get the ServerSessionData. If
	 * connection is ok, it calls submitImage with CRCsum in List<Integer>.
	 * 
	 * @return returns 'null' if there is a problem.
	 */
	public static UploadData getUploadInfos(ImageData imDat, String filename) {
		ImageServer.Client theClient = null;
		try {
			theClient = getConnection();
			if (theClient == null) {
				log.error("Client was null!");
				return null;
			}
			
			crc = new CrcFile(filename);
			log.info("Made CRCFile from " + filename);
			log.info("crc.getCrcSums( ).size = " + crc.getCrcSums().size());
			// log.info( "crc.getMasterSum() : " + crc.getMasterSum() );
			// for ( int i = 0; i < crc.getCrcSums().size() - 1; i++ ) {
			// log.info( "crc.getCRCSum() : " + crc.getCRCSum( i ) );
			// }
			return theClient
					.submitImage(sSD.sessionId, imDat, crc.getCrcSums());
		} catch (ImageDataException e) {
			if (e.isSetNumber()
					&& e.getNumber().equals(ImageDataError.INVALID_DATA)) {
				e.printStackTrace();
				// Data in the db is not valid
				// TODO: add e.message into DB;
			} else {
				e.printStackTrace();
			}
		} catch (UploadException e) {
			if (e.isSetNumber()
					&& e.getNumber().equals(UploadError.BROKEN_BLOCK)) {
				// A Block was transmitted 20 times unsuccessfully.
				// TODO: Mark the Image as corrupted.
			} else if (e.getNumber().equals(UploadError.INVALID_CRC)) {
				// The CRC sum contained errors
				try {
					crc = new CrcFile(filename);
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				if (!crc.isValid()) {
					// TODO: Mark CRC-file as corrupted.
				}
			} else {
				e.printStackTrace();
			}
		} catch (AuthorizationException e) {
			if (e.isSetNumber()
					&& e.getNumber().equals(
							AuthorizationError.NOT_AUTHENTICATED)) {
				// SessionID is not valid
				// TODO: Code for new SSID
			} else if (e.getNumber().equals(AuthorizationError.NO_PERMISSION)) {
				// not yet implemented.

			} else {
				e.printStackTrace();
			}
		} catch (UnrecoverableKeyException e) {
			log.error("UnrecoverableKeyException");
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			log.error("InvalidKeyException");
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			log.error("NoSuchAlgorithmException");
			e.printStackTrace();
		} catch (CertificateException e) {
			log.error("CertificateException");
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			log.error("FileNotFoundException");
			e.printStackTrace();
		} catch (KeyStoreException e) {
			log.error("KeyStoreException");
			e.printStackTrace();
		} catch (SignatureException e) {
			log.error("SignatureException");
			e.printStackTrace();
		} catch (IOException e) {
			log.error("IOException");
			e.printStackTrace();
		} catch (TException e) {
			log.error("TException");
			e.printStackTrace();
		}
		return null;
	}

	/***********************************************************************************************/
	/**
	 * Method for getting DonwloadInfos. Calls getConnection if client was null.
	 * You need to spezifie all Blocks you want to have in an List.
	 * 
	 * @return returns 'null' if there is a problem.
	 */
	public static DownloadData getDownloadInfos(DbImage imDat) {
		ImageServer.Client theClient = null;
		try {
			theClient = getConnection();
			if (theClient == null) {
				log.error("Client was null!");
				return null;
			}
			return theClient.getImage(sSD.sessionId, imDat.guid);
		} catch (ImageDataException e) {
			log.debug("In catch - blog of thrift connection");
			if (e.isSetNumber()
					&& e.getNumber().equals(ImageDataError.INVALID_DATA)) {
				// Data in the db is not valid
				// TODO: add e.message into DB;
			} else if (e.getNumber().equals(ImageDataError.UNKNOWN_IMAGE)) {
				// The image requested is not known.
				// TODO: change field image_syncMode, so the image is not asked
				// for again.
				// For now just changed status of image. Currently no possibility
				// for creating new useful state in DB. (Offenburg)
				log.info("Image not known. For skipping next time, mark as only_local.");
				imDat.updateStatus(Status.only_local);
				// Plus add a note in some way to mark as unknown by Server
			} else {
				e.printStackTrace();
			}
		} catch (AuthorizationException e) {
			if (e.isSetNumber()
					&& e.getNumber().equals(
							AuthorizationError.NOT_AUTHENTICATED)) {
				log.error("Not authenticated. SessionID is not valid.", e);
				// SessionID is not valid
				// TODO: Code for new SSID
			} else if (e.getNumber().equals(AuthorizationError.NO_PERMISSION)) {
				log.error("No permission error.", e);
			} else {
				e.printStackTrace();
			}
		} catch (UnrecoverableKeyException e) {
			log.error("UnrecoverableKeyException");
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			log.error("InvalidKeyException");
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			log.error("NoSuchAlgorithmException");
			e.printStackTrace();
		} catch (CertificateException e) {
			log.error("CertificateException");
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			log.error("FileNotFoundException");
			e.printStackTrace();
		} catch (KeyStoreException e) {
			log.error("KeyStoreException");
			e.printStackTrace();
		} catch (SignatureException e) {
			log.error("SignatureException");
			e.printStackTrace();
		} catch (IOException e) {
			log.error("IOException");
			e.printStackTrace();
		} catch (TException e) {
			log.error("TException");
			e.printStackTrace();
		}
		return null;
	}

	/***********************************************************************************************/
	/**
	 * This method checks if there is already a working connection. If not,
	 * newClient() establishes one. Also it does the Authentication if not done
	 * yet.
	 * 
	 * @return returns the client if successful.
	 */
	private static ImageServer.Client getConnection()
			throws UnrecoverableKeyException, NoSuchAlgorithmException,
			CertificateException, FileNotFoundException, KeyStoreException,
			IOException, InvalidKeyException, SignatureException {
		ImageServer.Client theClient = null;
		boolean isAuthenticated = false;
		if (client == null) {
			log.info("The global client was null. Making a new client ...");
			theClient = newClient();
			if (theClient == null) {
				log.debug("ThriftConnection: The client was null after newClient()");
				return null;
			}
		} else {
			log.info("The global Client was already used. Setting isAuthenticated = true.");
			theClient = client;
			isAuthenticated = true;
		}
		// here the client was already used so we are just assuming that the client is still
		// authenticated. Should be checked with the ping() method.
		// try {
		// isAuthenticated = theClient.ping();
		// } catch ( TException x ) {
		// theClient = newClient();
		// if ( theClient == null ) {
		// return null;
		// }
		// }
		if (!isAuthenticated) {
			log.info("ThriftConnection: Client not yet Authenticated. Trying...");
			if (theClient == null) {
				log.debug("The client was null");
				return null;
			}
			try {
				ByteBuffer tmpBuffer = theClient.startServerAuthentication(Globals
						.getOrganizationName());
				byte[] toEncrypt = new byte[tmpBuffer.remaining()];
				tmpBuffer.get(toEncrypt);
				log.info("The random String we want to encrypt: " + toEncrypt);
				log.info("Length of the random String : " + toEncrypt.length);
				AsymEncryptionHandler aeh = new AsymEncryptionHandler(Globals.getPrivateKey());
				
				byte[] byteArray = aeh.encryptMessage(toEncrypt);
				log.info( "Length of the byteArray of the random string after encryption :" + byteArray.length );
				ByteBuffer b = ByteBuffer.wrap( byteArray );
				log.info( "Length of the byteBuffer after encryption :" + b.remaining() );
				sSD = theClient.serverAuthenticate(
						Globals.getOrganizationName(),
						ByteBuffer.wrap(byteArray));
			} catch (ServerAuthenticationException e) {
				log.error("ThriftConnection: ServerAuthenticationException: Server Authetication was not sucessful.");
				e.printStackTrace();
				return null;
			} catch (TException e) {
				log.error("ThriftConnection: TException: Server Authetication was not sucessful.");
				e.printStackTrace();
				return null;
			}
			log.info("is Authenticated.");

		}
		client = theClient;
		return theClient;
	}

	/***********************************************************************************************/
	/**
	 * Method for creating a new Client for Thrift communication.
	 * 
	 * @throws IOException
	 */
	private static ImageServer.Client newClient() throws IOException {
		ImageServer.Client newClient = null;
		try {
			TTransport transport = new TFramedTransport( new TSocket(
					Globals.getMasterserverHost(),
					Globals.getThriftPort()));
			transport.open();
			TProtocol protocol = new TBinaryProtocol(transport);
			newClient = new ImageServer.Client(protocol);
			log.debug("ThriftConnection: Made a new Client");
		} catch (TTransportException tte) {
			log.error("Transport could not be opened. Couldn't create new client.");
			tte.printStackTrace();
			return null;
		}
		return newClient;
	}
}