f80aaa5a688af74b718931ba47bde1d2e0ecca7d
[charm.git] / src / libs / ck-libs / pythonCCS / PythonCCS-client.h
1 /* Security note:
2
3    The dynamic insertion of a code into a running program can generate bugs, and
4    potentially lead the parallel program to die. Moreover, a malicious client
5    can send a handcrafted message which corrupts the status of the server (i.e.
6    it can delete or modify the live data, or mess up with the interpreter
7    assigned to another user.
8
9    The current scheme does not try to resolve all conflicts and rely on the
10    correctness of the client to act honesly. In particular, the programmer
11    building the client should take care that if the current file is not included
12    (i.e. client build in a language different from c/c++) the class structure is
13    coherent with this file. Also the definition of the class inheriting from
14    PythonIterator needs to be coherent across client and server.
15 */
16
17 #include "converse.h"
18 #include <stdlib.h>
19 #include <string.h>
20 #include <stdio.h>
21 #include <netinet/in.h>
22
23 /* This class is empty, and should be reimplemented by the user */
24 class PythonIterator {
25   /* _It is strongly suggested to avoid pointers_, in which case none of the
26      following methods needs to be reimplemented. Instead, if pointers are used,
27      the following three methods have to be reimplemented to pack and unpack the
28      pointered values across client and server (in the same semantics of charm
29      packing)
30 */
31  public:
32   // return the total size of the object (after packing)
33   virtual int size() {return sizeof(*this);};
34
35   // pack the message into a contiguous memory and return the pointer to this
36   // memory. the memory needs to be persistent (i.e. cannot disappear) and will
37   // be freed automatically. It should not modify the original data.
38   virtual char *pack() {
39     void *memory = malloc(size());
40     memcpy (memory, this, size());
41     return (char *)memory;
42   };
43
44   // unpack needs to reposition the pointer in the case they are used
45   virtual void unpack() {};
46 };
47
48 /* This class contains a single unsigned 4 bytes integer, it is needed in order
49    to distinguish between PythonExecute and PythonPrint on the server side,
50    since a byte copy does not preserve class information.
51 */
52 class PythonAbstract {
53  public:
54   /* magic contains the size of the class passed, it is filled by the
55      constructors of the inheriting classes */
56   CmiUInt4 magic;
57
58   bool isFinished();
59   bool isExecute();
60   bool isPrint();
61   void unpack();
62 };
63
64 /* the unions with the "dummy" variables are to force a 64 bit space, which will
65    allow compatibility with 64 bit machines */
66 /* all the integers (CmiUInt4) are interpreted in network byte order */
67 class PythonExecute : private PythonAbstract {
68   friend class PythonObject;
69   friend class CpdPythonGroup;
70  private:
71   CmiUInt4 codeLength;
72   union {
73     char * code;
74     char dummy[8];
75   } code;
76
77   /* the following parameters are used when the iterator mode is invoked */
78   union {
79     char * methodName;
80     char dummy[8];
81   } methodName;
82   CmiUInt4 methodNameLength;
83   CmiUInt4 infoSize; /* must contain the size of the info structure passed */
84   union {
85     PythonIterator *info;
86     char dummy[8];
87   } info;
88
89   /* interpreter does not necessarely needs to be sent in byte order (since the
90      client does not need to read it), but it is to have a common interface with
91      java */
92   CmiUInt4 interpreter; /* request for an existing interpreter */
93   char flags;
94   /* flags has the following parameters: (bit 1 is the MSB)
95      bit 1: isPersistent
96      bit 2: keepPrint
97      bit 3: isHighLevel
98      bit 4: isIterate
99   */
100   static const char FLAG_PERSISTENT = 0x80;
101   static const char FLAG_KEEPPRINT = 0x40;
102   static const char FLAG_HIGHLEVEL = 0x20;
103   static const char FLAG_ITERATE = 0x10;
104   static const char FLAG_WAIT = 0x08;
105   static const char FLAG_NOCHECK = 0x04;
106  public:
107   static const CmiUInt4 localmagic = 37492037;
108
109   /* constructors */
110   /* by default, if the code is persistent, then the prints will be maintained */
111   PythonExecute(char *_code, bool _persistent=false, bool _highlevel=false, CmiUInt4 _interp=0);
112   PythonExecute(char *_code, char *_method, PythonIterator *_info, bool _persistent=false, bool _highlevel=false, CmiUInt4 _interp=0);
113   ~PythonExecute();
114
115   /* routines to set all parameters in the class */
116   void setCode(char *_set);
117   void setMethodName(char *_set);
118   void setIterator(PythonIterator *_set);
119   void setPersistent(bool _set);
120   void setIterate(bool _set);
121   void setHighLevel(bool _set);
122   void setKeepPrint(bool _set);
123   void setWait(bool _set);
124   void setInterpreter(CmiUInt4 i) { interpreter = i; };
125   void setNoCheck(bool _set);
126
127   bool isPersistent() { return flags & FLAG_PERSISTENT; };
128   bool isIterate() { return flags & FLAG_ITERATE; };
129   bool isHighLevel() { return flags & FLAG_HIGHLEVEL; };
130   bool isKeepPrint() { return flags & FLAG_KEEPPRINT; };
131   bool isWait() { return flags & FLAG_WAIT; };
132   CmiUInt4 getInterpreter() { return interpreter; };
133   bool isNoCheck() { return flags & FLAG_NOCHECK; };
134
135   int size();
136   char *pack();
137   void unpack();
138
139   void print(); /* for debugging */
140 };
141
142 class PythonPrint : private PythonAbstract {
143   friend class PythonObject;
144  private:
145   CmiUInt4 interpreter;
146   char flags;
147   /* flags has the following parameters: (bit 1 is the MSB)
148      bit 1: noWait
149      bit 2: kill previous request
150   */
151   static const char FLAG_WAIT = 0x80;
152   static const char FLAG_KILL = 0x40;
153  public:
154   static const CmiUInt4 localmagic = 989370215;
155   PythonPrint(CmiUInt4 _interp, bool Wait=true, bool Kill=false);
156
157   void setWait(bool _set);
158   bool isWait() { return flags & FLAG_WAIT; };
159
160   void setKill(bool _set);
161   bool isKill() { return flags & FLAG_KILL; };
162
163
164   int size() { return sizeof(*this); };
165   char *pack() { magic = htonl(magic); //interpreter = htonl(interpreter);
166  return (char *)this; };
167   void unpack() { interpreter = ntohl(interpreter); }
168
169   void print(); /* for debugging */
170 };
171
172 class PythonFinished : private PythonAbstract {
173   friend class PythonObject;
174  private:
175   CmiUInt4 interpreter;
176   char flags;
177   /* flags has the following parameters: (bit 1 is the MSB)
178      bit 1: noWait
179   */
180   static const char FLAG_WAIT = 0x80;
181  public:
182   static const CmiUInt4 localmagic = 738963580;
183   PythonFinished(CmiUInt4 _interp, bool Wait=true);
184
185   void setWait(bool _set);
186   bool isWait() { return flags & FLAG_WAIT; };
187
188   int size() { return sizeof(*this); };
189   char *pack() { magic = htonl(magic); //interpreter = htonl(interpreter);
190  return (char *)this; };
191   void unpack() { interpreter = ntohl(interpreter); }
192
193   void print(); /* for debugging */
194 };