source: trunk/CrypPlugins/PeerToPeerJobs/JobMessages.cs @ 1448

Last change on this file since 1448 was 1448, checked in by Sven Rech, 12 years ago

replaced all BigInteger stuff with the new BigInteger class from .net 4.0

But there are still problems with some plugins (Keysearcher, BigInteger Operations...)

File size: 15.5 KB
Line 
1/* Copyright 2010 Team CrypTool (Christian Arnold), Uni Duisburg-Essen
2
3   Licensed under the Apache License, Version 2.0 (the "License");
4   you may not use this file except in compliance with the License.
5   You may obtain a copy of the License at
6
7       http://www.apache.org/licenses/LICENSE-2.0
8
9   Unless required by applicable law or agreed to in writing, software
10   distributed under the License is distributed on an "AS IS" BASIS,
11   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   See the License for the specific language governing permissions and
13   limitations under the License.
14*/
15
16using System;
17using System.Collections.Generic;
18using System.Linq;
19using System.Text;
20using Cryptool.PluginBase.Miscellaneous;
21using System.Numerics;
22
23namespace Cryptool.Plugins.PeerToPeer.Jobs
24{
25    /// <summary>
26    /// use this ENUM only in the context with JobMessages!
27    /// </summary>
28    public enum MessageJobType
29    {
30        /// <summary>
31        /// indicates that this message contains a JobAccepted/JobDeclined Information
32        /// </summary>
33        JobAcceptanceInfo = 200,
34        /// <summary>
35        /// indicates that this message contains a JobResult
36        /// </summary>
37        JobResult = 201,
38        /// <summary>
39        /// indicates, that it has capacities to process a new job (use it only
40        /// for messages FROM the P2PJobAdmin TO the Manager)
41        /// </summary>
42        Free = 202,
43        /// <summary>
44        /// indicates that this message contains a JobPart (use it only for
45        /// messages FROM the Manager TO the P2PJobAdmin)
46        /// </summary>
47        JobPart = 203,
48        /// <summary>
49        /// Manager should send this msgType to all requesting
50        /// workers, when it has no more jobs left
51        /// </summary>
52        NoMoreJobsLeft = 204
53    }
54
55    public static class JobMessages
56    {
57        #region Detection and Type-Request of JobMessages
58
59        /// <summary>
60        /// returns true, when the first byte indicates, that this is a JobMessage
61        /// </summary>
62        /// <param name="firstByte">first byte of a message</param>
63        /// <returns></returns>
64        public static bool IsJobMessageType(byte firstByte)
65        {
66            foreach (MessageJobType msgJobType in Enum.GetValues(typeof(MessageJobType)))
67            {
68                if ((MessageJobType)firstByte == msgJobType)
69                    return true;
70            }
71            return false;
72        }
73
74        /// <summary>
75        /// use this method only, when you are sure, that the first byte indicates
76        /// a JobMessage (use IsJobMessageType first), then it will return the
77        /// special MessageJobType
78        /// </summary>
79        /// <param name="firstByte">First byte of the message</param>
80        /// <returns></returns>
81        public static MessageJobType GetMessageJobType(byte firstByte)
82        {
83            foreach (MessageJobType msgJobType in Enum.GetValues(typeof(MessageJobType)))
84            {
85                if ((MessageJobType)firstByte == msgJobType)
86                    return msgJobType;
87            }
88            throw (new Exception("No other JobMessageTypes are available!"));
89        }
90
91        #endregion
92
93        /// <summary>
94        /// integrates the serialized JobPart into the DistributableJob-specific
95        /// communication protocol - returns a completely compatible DistributableJob-Message
96        /// </summary>
97        /// <param name="jobId">the jobId of the actual JobPart</param>
98        /// <param name="data">the already serialized JobPart-data</param>
99        /// <returns></returns>
100        public static byte[] CreateJobPartMessage(BigInteger jobId, byte[] data)
101        {
102            byte[] jobIdBytes = SerializeJobId(jobId);
103
104            byte[] result = new byte[jobIdBytes.Length + data.Length + 1];
105            result[0] = (byte)MessageJobType.JobPart;
106
107            Buffer.BlockCopy(jobIdBytes, 0, result, 1, jobIdBytes.Length);
108            Buffer.BlockCopy(data, 0, result, jobIdBytes.Length + 1, data.Length);
109
110            return result;
111        }
112
113        /// <summary>
114        /// Fetches the serialized JobPart data and the JobId of the JobPart out of
115        /// the DistributableJob-specific message. If the message doesn't fit to the
116        /// communication protocol, this method returns null, otherwise the raw serialized
117        /// JobPart data!
118        /// </summary>
119        /// <param name="data">DistributableJob-specific message, which was proved that it is a JobPartMessage before</param>
120        /// <param name="jobId">catches the JobId out of the raw byte data and returns it, too</param>
121        /// <returns></returns>
122        public static byte[] GetJobPartMessage(byte[] data, out BigInteger jobId)
123        {
124            byte[] serializedJobPart = null;
125            jobId = -1;
126            if ((MessageJobType)data[0] == MessageJobType.JobPart)
127            {
128                byte[] tailBytes = new byte[data.Length - 1];
129
130                Buffer.BlockCopy(data, 1, tailBytes, 0, tailBytes.Length);
131                int bytesLeft;
132                jobId = DeserializeJobId(tailBytes, out bytesLeft);
133
134                serializedJobPart = new byte[bytesLeft];
135                Buffer.BlockCopy(tailBytes, tailBytes.Length - bytesLeft, serializedJobPart, 0, serializedJobPart.Length);
136            }
137            return serializedJobPart;
138        }
139
140        /* Byte representation of a Job Result Message:
141         * 1 Byte:  MessageJobType
142         * n Bytes: serialized job id (incl. byteLen; use DeserializeBigInt!)
143         * n Bytes: serialized job result */
144        /// <summary>
145        /// integrates the serialized JobResult into the DistributableJob-specific
146        /// communication protocol - returns a completely compatible DistributableJob-Message
147        /// </summary>
148        /// <param name="jobId">the jobId of the actual JobPart</param>
149        /// <param name="data">the already serialized JobResult-data</param>
150        /// <returns></returns>
151        public static byte[] CreateJobResultMessage(BigInteger jobId, byte[] data)
152        {
153            byte[] jobIdBytes = SerializeJobId(jobId);
154
155            byte[] result = new byte[jobIdBytes.Length + data.Length + 1];
156            result[0] = (byte)MessageJobType.JobResult;
157
158            Buffer.BlockCopy(jobIdBytes, 0, result, 1, jobIdBytes.Length);
159            Buffer.BlockCopy(data, 0, result, jobIdBytes.Length + 1, data.Length);
160
161            return result;
162        }
163
164        /// <summary>
165        /// Fetches the serialized JobResult data and the JobId of the JobResult out of
166        /// the DistributableJob-specific message. If the message doesn't fit to the
167        /// communication protocol, this method returns null, otherwise the raw serialized
168        /// JobResult data!
169        /// </summary>
170        /// <param name="data">DistributableJob-specific message, which was proved that it is a JobResultMessage before</param>
171        /// <param name="jobId">catches the JobId out of the raw byte data and returns it, too</param>
172        /// <returns></returns>
173        public static byte[] GetJobResult(byte[] data, out BigInteger jobId)
174        {
175            byte[] serializedJobResult = null;
176            jobId = -1;
177            if ((MessageJobType)data[0] == MessageJobType.JobResult)
178            {
179                byte[] tailBytes = new byte[data.Length - 1];
180
181                Buffer.BlockCopy(data, 1, tailBytes, 0, tailBytes.Length);
182                int bytesLeft;
183                jobId = DeserializeJobId(tailBytes, out bytesLeft);
184                serializedJobResult = new byte[bytesLeft];
185                Buffer.BlockCopy(tailBytes, tailBytes.Length - bytesLeft, serializedJobResult, 0, serializedJobResult.Length);
186            }
187            return serializedJobResult;
188        }
189
190        /* Byte representation of a job acceptance Message:
191         * 1 Byte:  MessageJobType
192         * n Bytes: bool JobAcceptance
193         * n Bytes: serialized Job Id (incl. length, use DeserializeJobId!)*/
194        /// <summary>
195        /// creates a DistributableJob-specific message, which contains information
196        /// about the job acceptance (Accepted or Declined)
197        /// </summary>
198        /// <param name="jobId">the jobId of the actual JobPart</param>
199        /// <param name="jobAccepted">true, when JobPart was accepted by the P2PJobAdmin, otherwise false</param>
200        /// <returns></returns>
201        public static byte[] CreateJobAcceptanceMessage(BigInteger jobId, bool jobAccepted)
202        {
203            byte[] serializedJobId = SerializeJobId(jobId);
204
205            byte jobAcceptedByte = Convert.ToByte(jobAccepted);
206
207            byte[] serializedData = new byte[serializedJobId.Length + 2];
208            serializedData[0] = (byte)MessageJobType.JobAcceptanceInfo;
209            serializedData[1] = jobAcceptedByte;
210            Buffer.BlockCopy(serializedJobId, 0, serializedData, 2, serializedJobId.Length);
211
212            return serializedData;
213        }
214
215        /// <summary>
216        /// Fetches the JobAcceptance-Result out of the DistributableJob-specific
217        /// message. Returns true, if JobPart was accepted by the P2PJobAdmin,
218        /// otherwise false. Additionally it returns the JobId of the accepted/declined
219        /// JobPart.
220        /// </summary>
221        /// <param name="data">DistributableJob-specific message</param>
222        /// <param name="jobId">catches the JobId out of the raw byte data and returns it, too</param>
223        /// <returns></returns>
224        public static bool GetJobAcceptanceMessage(byte[] data, out BigInteger jobId)
225        {
226            bool result;
227            if ((MessageJobType)data[0] == MessageJobType.JobAcceptanceInfo)
228            {
229                result = Convert.ToBoolean(data[1]);
230                byte[] jobIdBytes = new byte[data.Length - 2];
231                Buffer.BlockCopy(data, 2, jobIdBytes, 0, jobIdBytes.Length);
232                int neverMind;
233                jobId = DeserializeJobId(jobIdBytes, out neverMind);
234            }
235            else
236            {
237                throw (new Exception("byte[] representation wasn't a JobAcceptance Message!"));
238            }
239            return result;
240        }
241
242        /// <summary>
243        /// When a P2PJobAdmin is ready to get a new JobPart for processing,
244        /// it have to send a "Free Worker"-Status-Message. This method returns
245        /// a DistributableJob-specific message.
246        /// </summary>
247        /// <param name="free">true, if worker is ready for processing new, incoming JobParts.</param>
248        /// <returns></returns>
249        public static byte[] CreateFreeWorkerStatusMessage(bool free)
250        {
251            byte[] retValue = new byte[2];
252            retValue[0] = (byte)MessageJobType.Free;
253            if (free)
254                retValue[1] = 1;
255            else
256                retValue[1] = 0;
257            return retValue;
258        }
259
260        /// <summary>
261        /// When a P2PJobAdmin is ready for processing new incoming JobParts
262        /// it sends a "Free Worker"-Status-Message. This method returns true
263        /// when Worker is ready (so send a new JobPart to it), otherwise false
264        /// </summary>
265        /// <param name="msg">the whole, DistributableJob-specific message</param>
266        /// <returns></returns>
267        public static bool GetFreeWorkerStatusMessage(byte[] msg)
268        {
269            bool retValue = false;
270            if ((MessageJobType)msg[0] == MessageJobType.Free && msg.Length == 2)
271            {
272                if (msg[1] == 0)
273                    retValue = false;
274                else
275                    retValue = true;
276            }
277            return retValue;
278        }
279
280        // TODO: Create NoMoreJobsLeft Msg
281
282        /// <summary>
283        /// When the Manager has no more jobs left, it should send a "no more
284        /// jobs left" message to all job-requesting Workers.
285        /// </summary>
286        /// <returns>serialized "no more jobs left" message</returns>
287        public static byte[] CreateNoMoreJobsLeftMessage()
288        {
289            byte[] retValue = new byte[2];
290            retValue[0] = (byte)MessageJobType.NoMoreJobsLeft;
291            retValue[1] = 1;
292            return retValue;
293        }
294
295        /// <summary>
296        /// Only workers can receive this message type. Manager sent
297        /// this Msg, when it has no more jobs left to allocate.
298        /// </summary>
299        /// <param name="msg"></param>
300        /// <returns></returns>
301        public static bool GetNoMoreJobsLeftMessage(byte[] msg)
302        {
303            bool retValue = false;
304            if ((MessageJobType)msg[0] == MessageJobType.NoMoreJobsLeft && msg.Length == 2)
305            {
306                if (msg[1] == 1)
307                    retValue = true;
308            }
309            return retValue;
310        }
311
312        #region (De-)Serialization of JobId
313
314        public static byte[] SerializeJobId(BigInteger jobId)
315        {
316            byte[] resultByte = null;
317            if (jobId != null)
318            {
319                // Note, there is a Bug in BigInt: BigInt b = 256; => b.dataLength = 1 -- it should be 2!
320                // As a workarround rely on getBytes().Length (the null bytes for the BigInt 0 should be fixed now)
321                byte[] jobIdBytes = jobId.ToByteArray();
322                byte[] jobIdBytesLen = BitConverter.GetBytes(jobIdBytes.Length);
323             
324                resultByte = new byte[jobIdBytes.Length + jobIdBytesLen.Length];
325               
326                Buffer.BlockCopy(jobIdBytesLen, 0, resultByte, 0, jobIdBytesLen.Length);
327                Buffer.BlockCopy(jobIdBytes, 0, resultByte, jobIdBytesLen.Length, jobIdBytes.Length);
328            }
329            return resultByte;
330        }
331
332        /// <summary>
333        /// Deserialized a jobId from any byte[] array. Requirement: The byte[] has
334        /// to start with a four byte (int32) JobId-Length-Information and have than enough
335        /// bytes left to deserialize the BigInteger Value. If any bytes left after
336        /// deserializing the JobId, the out value will specify this amount.
337        /// </summary>
338        /// <param name="serializedJobId">The byte[] has to start with a four bytes (int32)
339        /// JobId-Length-Information and have than enough bytes left to deserialize
340        /// the BigInteger Value</param>
341        /// <param name="bytesLeft">If any bytes left after
342        /// deserializing the JobId, the out value will specify this amount.</param>
343        /// <returns></returns>
344        public static BigInteger DeserializeJobId(byte[] serializedJobId, out int bytesLeft)
345        {
346            // byte length of Int32
347            int iInt32 = 4;
348
349            BigInteger result = -1;
350            bytesLeft = serializedJobId.Length;
351            if (serializedJobId != null && serializedJobId.Length > iInt32)
352            {
353                byte[] bigIntByteLen = new byte[iInt32];
354                Buffer.BlockCopy(serializedJobId, 0, bigIntByteLen, 0, bigIntByteLen.Length);
355                int bigIntLen = BitConverter.ToInt32(bigIntByteLen, 0);
356                byte[] bigIntByte = new byte[bigIntLen];
357                Buffer.BlockCopy(serializedJobId, bigIntByteLen.Length, bigIntByte, 0, bigIntByte.Length);
358                result = new BigInteger(bigIntByte);
359                bytesLeft = serializedJobId.Length - iInt32 - bigIntByte.Length;
360            }
361            return result;
362        }
363#endregion
364    }
365}
Note: See TracBrowser for help on using the repository browser.