]> git.vomp.tv Git - vompserver.git/blob - serialize.c
15 years that line of code has been waiting to crash
[vompserver.git] / serialize.c
1 /*
2     Copyright 2004-2005 Chris Tallon, Andreas Vogel
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP 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
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "serialize.h"
22 #include <stdlib.h>
23 #include <arpa/inet.h>
24 #ifndef SNPRINTF
25 #define SNPRINTF snprintf
26 #endif
27
28 #define BUFFERINCREASE 1024
29
30 int SerializeBuffer::seek(int amount) {
31   UCHAR *np=current+amount;
32   if (np < start || np > end) return -1;
33   current=np;
34   return 0;
35 }
36
37 void SerializeBuffer::rewind() {
38   current=start;
39 }
40
41 int SerializeBuffer::checkSpace(int amount) {
42   if ((current+amount) <= end) return 0;
43   if (owning && autoincrease) {
44      if (start+size > current+amount) {
45        end=start+size;
46        return 0;
47      }
48      UCHAR *ns=new UCHAR[size+BUFFERINCREASE];
49      if (!ns) return -1;
50      memcpy(ns,start,end-start);
51      size=size+BUFFERINCREASE;
52      end=ns+size;
53      if (useMalloc) free( start);
54      else delete [] start;
55      start=ns;
56      return 0;
57   }
58   return -1;
59 }
60
61 SerializeBuffer::~SerializeBuffer() {
62   if (owning) {
63     if (useMalloc) free(start);
64     else delete[] start;
65     start=NULL;
66   }
67 }
68 SerializeBuffer::SerializeBuffer(ULONG sz,bool isMalloc,bool ai){
69   autoincrease=ai;
70   useMalloc=isMalloc;
71   if (isMalloc) {
72     start=(UCHAR *)malloc(sz);
73   }
74   else {
75     start=new UCHAR[sz];
76   }
77   end=start;
78   current=start;
79   size=sz;
80   owning=true;
81 }
82     //constructor for SerializeBuffers with external buffers
83 SerializeBuffer::SerializeBuffer(UCHAR *buffer,ULONG sz,bool ow,bool isMalloc,bool ai) {
84   useMalloc=isMalloc;
85   autoincrease=ai;
86   owning=ow;
87   size=sz;
88   start=buffer;
89   current=start;
90   end=start+size;
91 }
92 /**
93   * helper for serialize and deserialize
94   * always return != if no space
95   * advance buffer pointer
96   */
97
98 int SerializeBuffer::encodeLong(ULONG data) {
99   if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
100   *((ULONG *)(current))=htonl(data); 
101   current+=sizeof(ULONG);
102   return 0;
103 }
104 int SerializeBuffer::encodeShort(USHORT data) {
105   if (checkSpace( (int)sizeof(USHORT))!=0) return -1;
106   *((USHORT *)(current))=htons(data); 
107   current+=sizeof(USHORT);
108   return 0;
109 }
110 int SerializeBuffer::encodeByte(UCHAR data) {
111   if (checkSpace( (int)sizeof(UCHAR))!=0) return -1;
112   *((UCHAR *)(current))=data; 
113   current+=sizeof(UCHAR);
114   return 0;
115 }
116 int SerializeBuffer::encodeLongLong(ULLONG data) {
117   if (checkSpace( (int)sizeof(ULLONG))!=0) return -1;
118   *((ULONG *)(current))=htonl((data>>32) & 0xffffffff); 
119   current+=sizeof(ULONG);
120   *((ULONG *)(current))=htonl(data & 0xffffffff); 
121   current+=sizeof(ULONG);
122   return 0;
123 }
124 //string: 4 len, string with 0
125 int SerializeBuffer::encodeString(const char *str) {
126   if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
127   ULONG len=0;
128   if (str) len=strlen(str)+1;
129   *((ULONG *)(current))=htonl(len); 
130   current+=sizeof(ULONG);
131   if (len == 0) return 0;
132   if (checkSpace((int)len)!=0) return -1;
133   strcpy((char *) current,str);
134   current+=len;
135   return 0;
136 }
137 int SerializeBuffer::decodeLong( int &data) {
138   if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
139   data=(int)ntohl(*((ULONG *)(current))); 
140   current+=sizeof(ULONG);
141   return 0;
142 }
143 int SerializeBuffer::decodeLong(ULONG &data) {
144   if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
145   data=ntohl(*((ULONG *)(current))); 
146   current+=sizeof(ULONG);
147   return 0;
148 }
149 int SerializeBuffer::decodeShort(USHORT &data) {
150   if (checkSpace( (int)sizeof(USHORT))!=0) return -1;
151   data=ntohs(*((USHORT *)(current))); 
152   current+=sizeof(USHORT);
153   return 0;
154 }
155 int SerializeBuffer::decodeByte(UCHAR &data) {
156   if (checkSpace( (int)sizeof(UCHAR))!=0) return -1;
157   data=*((UCHAR *)current);
158   current+=sizeof(UCHAR);
159   return 0;
160 }
161 int SerializeBuffer::decodeLongLong(ULLONG &data) {
162   if (checkSpace( (int)sizeof(ULLONG))!=0) return -1;
163   ULLONG hd=ntohl(*((ULONG *)(current))); 
164   current+=sizeof(ULONG);
165   ULLONG ld=ntohl(*((ULONG *)(current))); 
166   current+=sizeof(ULONG);
167   data=(hd << 32) | ld;
168   return 0;
169 }
170 //string: 4 len, string with 0
171 int SerializeBuffer::decodeString(ULONG &len, char *&strbuf) {
172   strbuf=NULL;
173   len=0;
174   if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
175   len=ntohl(*((ULONG *)(current))); 
176   current+=sizeof(ULONG);
177   if (len == 0) return 0;
178   if (checkSpace((int)len)!=0) return -1;
179   strbuf=new char[len];
180   strncpy(strbuf,(char *)current,len);
181   *(strbuf+len-1)=0;
182   current+=len;
183   return 0;
184 }
185
186
187 UCHAR * SerializeBuffer::steelBuffer() {
188   UCHAR *rt=start;
189   owning=false;
190   autoincrease=false;
191   return rt;
192 }
193
194 int Serializable::getSerializedStringLen(const char * str) {
195   int rt=4;
196   if (str) rt+=strlen(str)+1;
197   return rt;
198 }
199
200 USHORT Serializable::getVersion() {
201   return version;
202 }
203
204
205 Serializable::Serializable() {
206   version=1;
207 }
208 Serializable::~Serializable(){}
209
210 int Serializable::getSerializedLen() {
211   //2version+4len
212   return 6 + getSerializedLenImpl();
213 }
214 int Serializable::serialize(SerializeBuffer *b) {
215   UCHAR *ptr=b->getCurrent();
216   if (b->encodeShort(version) != 0) return -1;
217   if (b->encodeLong(0) != 0) return -1; //dummy len
218   if (serializeImpl(b) != 0) return -1;
219   UCHAR *ep=b->getCurrent();
220   //now write the len
221   int len=ep-ptr-6;
222   if (len < 0) return -1 ; //internal error
223   b->seek(ptr-ep+2); //to len field
224   if (b->encodeLong(len) != 0) return -1;
225   b->seek(ep-b->getCurrent()); //back to end
226   return 0;
227 }
228
229 int Serializable::deserialize(SerializeBuffer *b) {
230   USHORT vers=0;
231   if (b->decodeShort(vers) != 0) return -1;
232   ULONG len=0;
233   if (b->decodeLong(len) != 0) return -1;
234   UCHAR *data=b->getCurrent();
235   if (data+len > b->getEnd()) return -1;
236   //TODO: set end temp. to current+len
237   //for better error handling in deserializeImpl
238   if (deserializeImpl(b) != 0) return -1;
239   //ensure we go to end of this element regardless of the things we know
240   b->seek(data+len-b->getCurrent());
241   return 0;
242 }
243   
244 SerializableList::SerializableList() {
245   version=1;
246   encodeOnly=false;
247 }
248 SerializableList::~SerializableList(){}
249
250 int SerializableList::addParam(Serializable *p,USHORT v) {
251   if (v < version || p == NULL) return -1;
252   Pentry entry;
253   entry.ptype=TSER;
254   entry.ptr.pser=p;
255   entry.version=v;
256   list.push_back(entry);
257   version=v;
258   return 0;
259 }
260 int SerializableList::addParam(USHORT *p,USHORT v) {
261   if (v < version || p == NULL) return -1;
262   Pentry entry;
263   entry.ptype=TUSHORT;
264   entry.ptr.pshort=p;
265   entry.version=v;
266   list.push_back(entry);
267   version=v;
268   return 0;
269 }
270 int SerializableList::addParam(ULONG *p,USHORT v) {
271   if (v < version || p == NULL) return -1;
272   Pentry entry;
273   entry.ptype=TULONG;
274   entry.ptr.plong=p;
275   entry.version=v;
276   list.push_back(entry);
277   version=v;
278   return 0;
279 }
280 int SerializableList::addParam(ULLONG *p,USHORT v) {
281   if (v < version || p == NULL) return -1;
282   Pentry entry;
283   entry.ptype=TULLONG;
284   entry.ptr.pllong=p;
285   entry.version=v;
286   list.push_back(entry);
287   version=v;
288   return 0;
289 }
290 int SerializableList::addParam(char **p,USHORT v) {
291   if (v < version || p == NULL) return -1;
292   Pentry entry;
293   entry.ptype=TCHAR;
294   entry.ptr.pchar=p;
295   entry.version=v;
296   list.push_back(entry);
297   version=v;
298   return 0;
299 }
300
301 bool SerializableList::Pentry::isEqual(void *p,SerializableList::Ptypes t) {
302   void *cmp=NULL;
303   switch(t) {
304     case TUSHORT:
305       cmp=(void *)ptr.pshort;
306       break;
307     case TULONG:
308       cmp=(void *)ptr.plong;
309       break;
310     case TULLONG:
311       cmp=(void *)ptr.pllong;
312       break;
313     case TSER:
314       cmp=(void *)ptr.pser;
315       break;
316     case TCHAR:
317       cmp=(void *)ptr.pchar;
318       break;
319     case TUNKNOWN:
320       break;
321   }
322   return p==cmp;
323 }
324
325 SerializableList::Pentry *SerializableList::findEntry(void *p,SerializableList::Ptypes t) {
326   for (vector<Pentry>::iterator it=list.begin();it<list.end();it++) {
327     if ( (*it).isEqual(p,t)) return &(*it);
328   }
329   return NULL;
330 }
331 bool SerializableList::isDeserialized(Serializable *p){
332   SerializableList::Pentry *e=findEntry(p,TSER);
333   if (!e) return false;
334   return e->isDeserialized;
335 }
336 bool SerializableList::isDeserialized(USHORT *p){
337   SerializableList::Pentry *e=findEntry(p,TUSHORT);
338   if (!e) return false;
339   return e->isDeserialized;
340 }
341 bool SerializableList::isDeserialized(ULONG *p){
342   SerializableList::Pentry *e=findEntry(p,TULONG);
343   if (!e) return false;
344   return e->isDeserialized;
345 }
346
347 bool SerializableList::isDeserialized(ULLONG *p){
348   SerializableList::Pentry *e=findEntry(p,TULLONG);
349   if (!e) return false;
350   return e->isDeserialized;
351 }
352
353 bool SerializableList::isDeserialized(char **p){
354   SerializableList::Pentry *e=findEntry(p,TCHAR);
355   if (!e) return false;
356   return e->isDeserialized;
357 }
358
359 int SerializableList::getSerializedLenImpl(){
360   int rt=0;
361   for (vector<Pentry>::iterator it=list.begin();it<list.end();it++) {
362     switch((*it).ptype){
363       case TUSHORT:
364         rt+=sizeof(USHORT);
365         break;
366       case TULONG:
367         rt+=sizeof(ULONG);
368         break;
369       case TULLONG:
370         rt+=sizeof(ULLONG);
371         break;
372       case TCHAR:
373         rt+=getSerializedStringLen(*((*it).ptr.pchar));
374         break;
375       case TSER:
376         rt+=(*it).ptr.pser->getSerializedLen();
377         break;
378       case TUNKNOWN:
379         break;
380     }
381   }
382   return rt;
383 }
384
385 int SerializableList::serializeImpl(SerializeBuffer *b){
386   for (vector<Pentry>::iterator it=list.begin();it<list.end();it++) {
387     switch((*it).ptype){
388       case TUSHORT:
389         if (b->encodeShort(*(*it).ptr.pshort) != 0) return -1;
390         break;
391       case TULONG:
392         if (b->encodeLong(*(*it).ptr.plong) != 0) return -1;
393         break;
394       case TULLONG:
395         if (b->encodeLongLong(*(*it).ptr.pllong) != 0) return -1;
396         break;
397       case TCHAR:
398         if (b->encodeString(*(*it).ptr.pchar) != 0) return -1;
399         break;
400       case TSER:
401         if ((*it).ptr.pser->serialize(b) != 0) return -1;
402         break;
403       case TUNKNOWN:
404         break;
405     }
406   }
407   return 0;
408 }
409
410 int SerializableList::deserializeImpl(SerializeBuffer *b){
411   ULONG dlen=0;
412   for (vector<Pentry>::iterator it=list.begin();it<list.end();it++) {
413     if ((*it).version > version) {
414       //OK - we received an older version - stop here
415       break;
416     }
417     switch((*it).ptype){
418       case TUSHORT:
419         if (b->decodeShort(*(*it).ptr.pshort) != 0) return -1;
420         break;
421       case TULONG:
422         if (b->decodeLong(*(*it).ptr.plong) != 0) return -1;
423         break;
424       case TULLONG:
425         if (b->decodeLongLong(*(*it).ptr.pllong) != 0) return -1;
426         break;
427       case TCHAR:
428         if (b->decodeString(dlen,*(*it).ptr.pchar) != 0) return -1;
429         break;
430       case TSER:
431         if ((*it).ptr.pser->deserialize(b) != 0) return -1;
432         break;
433       case TUNKNOWN:
434         break;
435     }
436     (*it).isDeserialized=true;
437   }
438   return 0;
439 }
440
441