00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <stdarg.h>
00021
00022 #include <vos/metaobjects/misc/cod.hh>
00023 #include <vos/metaobjects/property/property.hh>
00024
00025 #ifdef WIN32
00026 #define ZLIB_DLL
00027 #endif
00028
00029 #include <zlib.h>
00030
00031 COD::COD(iostream& io, LocalSite& l)
00032 : f(&io), ls(l), offset(0), buffersize(0), buffer(0)
00033 {
00034 ls.acquire();
00035 }
00036
00037 COD::COD(LocalSite& l)
00038 : f(0), ls(l), offset(0), buffersize(0), buffer(0)
00039 {
00040 ls.acquire();
00041 }
00042
00043
00044 COD::~COD()
00045 {
00046 ls.release();
00047 if(buffer) free(buffer);
00048
00049 clear();
00050 }
00051
00052 void COD::setStream(iostream& io)
00053 {
00054 f = &io;
00055 }
00056
00057 void COD::clear()
00058 {
00059 for(unsigned int i = 0; i < vobjectorder.size(); i++) {
00060 if(vobjectorder[i]) {
00061 if(vobjectorder[i]->vobject) vobjectorder[i]->vobject->release();
00062 if(vobjectorder[i]->mb) vobjectorder[i]->mb->release();
00063 delete vobjectorder[i];
00064 }
00065 }
00066 vobjectorder.resize(0);
00067 vobjectTable.clear();
00068 }
00069
00070 int COD::addVobject(Vobject* v, bool portable, bool saveChildren)
00071 {
00072 v->acquire();
00073 Entry* e = new Entry;
00074 e->vobject = v;
00075 e->mb = new MessageBlock();
00076 e->vobject->saveState(*e->mb, e->types, portable);
00077 e->savechildren = saveChildren;
00078
00079 vobjectTable[v->getName()] = e;
00080 vobjectorder.push_back(e);
00081 e->pos = vobjectorder.size() - 1;
00082 return e->pos;
00083 }
00084
00085 int COD::addVobject(Vobject* v, const set<string>& types, MessageBlock* mb, bool saveChildren)
00086 {
00087 v->acquire();
00088 Entry* e = new Entry;
00089 e->vobject = v;
00090 mb->acquire();
00091 e->mb = mb;
00092 e->types = types;
00093 e->savechildren = saveChildren;
00094
00095 vobjectTable[v->getName()] = e;
00096 vobjectorder.push_back(e);
00097 e->pos = vobjectorder.size() - 1;
00098 return e->pos;
00099 }
00100
00101 int COD::addVobject(Vobject* v, const deque<string>& types, MessageBlock* mb, bool saveChildren)
00102 {
00103 v->acquire();
00104 Entry* e = new Entry;
00105 e->vobject = v;
00106 mb->acquire();
00107 e->mb = mb;
00108 e->savechildren = saveChildren;
00109
00110 for(unsigned int i = 0; i < types.size(); i++) {
00111 e->types.insert(types[i]);
00112 }
00113
00114 vobjectTable[v->getName()] = e;
00115 vobjectorder.push_back(e);
00116 e->pos = vobjectorder.size() - 1;
00117 return e->pos;
00118 }
00119
00120
00121 int COD::numVobjects()
00122 {
00123 return vobjectorder.size();
00124 }
00125
00126 COD::Entry* COD::getVobject(const string& name)
00127 {
00128 map<string, Entry*>::iterator i = vobjectTable.find(name);
00129 if(i != vobjectTable.end()) return (*i).second;
00130 else return 0;
00131 }
00132
00133 COD::Entry* COD::getVobject(int pos)
00134 {
00135 if(pos < 0) pos += vobjectorder.size() + 1;
00136 if(pos >= vobjectorder.size()) return 0;
00137 else return vobjectorder[pos];
00138 }
00139
00140 void COD::removeVobject(const string& name)
00141 {
00142 map<string, Entry*>::iterator i = vobjectTable.find(name);
00143 if(i == vobjectTable.end()) return;
00144 Entry* e = (*i).second;
00145 vobjectTable.erase(i);
00146 vobjectorder.erase(vobjectorder.begin() + e->pos);
00147
00148 e->vobject->release();
00149 e->mb->release();
00150
00151 delete e;
00152 }
00153
00154 void COD::removeVobject(int pos)
00155 {
00156 if(pos < 0) pos += vobjectorder.size() + 1;
00157 if(pos >= vobjectorder.size()) return;
00158
00159 Entry* e = vobjectorder[pos];
00160
00161 vobjectorder.erase(vobjectorder.begin() + pos);
00162 vobjectTable.erase(e->vobject->getName());
00163
00164 e->vobject->release();
00165 e->mb->release();
00166
00167 delete e;
00168 }
00169
00170
00171 int COD::writeObjectDesc(Entry* e, bool doWrite)
00172 {
00173 unsigned char buffer[65361];
00174 int numbytes = 0;
00175 int nb;
00176
00177 vRef<Vobject::ParentChildRelation> pcr = ls.findChild(e->vobject->getName());
00178
00179 nb = pack(buffer, sizeof(buffer), "Sls",
00180 e->vobject->getName().c_str(), e->vobject->getName().size(),
00181 pcr->position,
00182 e->types.size());
00183 if(doWrite) write(buffer, nb);
00184 numbytes += nb;
00185
00186 for(Vobject::TypeSet::const_iterator i = e->types.begin(); i != e->types.end(); i++)
00187 {
00188 nb = pack(buffer, sizeof(buffer), "S", (*i).c_str(), (*i).size());
00189 if(doWrite) write(buffer, nb);
00190 numbytes += nb;
00191 }
00192
00193 nb = pack(buffer, sizeof(buffer), "s", e->mb->numMessages());
00194 if(doWrite) write(buffer, nb);
00195 numbytes += nb;
00196
00197 for(int i = 0; i < e->mb->numMessages(); i++) {
00198 vRef<Message> m = e->mb->getMessage(i);
00199 nb = pack(buffer, sizeof(buffer), "Ss", m->getMethod().c_str(),
00200 m->getMethod().size(), m->getNumFields());
00201 if(doWrite) write(buffer, nb);
00202 numbytes += nb;
00203
00204 for(int n = 0; n < m->getNumFields(); n++) {
00205 const Message::Field& fl = m->getField(n);
00206 nb = pack(buffer, sizeof(buffer), "Sl", fl.key.c_str(), fl.key.size(), fl.value.size());
00207 if(doWrite) write(buffer, nb);
00208 numbytes += nb;
00209
00210 nb = fl.value.size();
00211 if(doWrite) write(fl.value.c_str(), nb);
00212 numbytes += nb;
00213 }
00214 }
00215
00216 return numbytes;
00217 }
00218
00219 int COD::writeObjectChildren(Vobject* child, bool doWrite)
00220 {
00221 unsigned char buffer[65361];
00222 int numbytes = 0;
00223 int nb;
00224
00225 const Vobject::ChildList& cl2 = child->getChildren();
00226 nb = pack(buffer, sizeof(buffer), "Sl", child->getName().c_str(),
00227 child->getName().size(), cl2.size());
00228 if(doWrite) write(buffer, nb);
00229 numbytes += nb;
00230 for(unsigned int n = 0; n < cl2.size(); n++) {
00231 Vobject::ParentChildRelation* pcr2 = cl2[n];
00232 nb = pack(buffer, sizeof(buffer), "S",
00233 pcr2->contextual_name.c_str(),
00234 pcr2->contextual_name.size());
00235 if(doWrite) write(buffer, nb);
00236 numbytes += nb;
00237 if(pcr2 && pcr2->child) {
00238 if(pcr2->child->isLocal() && vobjectTable.count(pcr2->child->getName())) {
00239 nb = pack(buffer, sizeof(buffer), "S",
00240 pcr2->child->getName().c_str(),
00241 pcr2->child->getName().size());
00242 if(doWrite) write(buffer, nb);
00243 numbytes += nb;
00244 } else {
00245 nb = pack(buffer, sizeof(buffer), "S",
00246 pcr2->child->getURL().getString().c_str(),
00247 pcr2->child->getURL().getString().size());
00248 if(doWrite) write(buffer, nb);
00249 numbytes += nb;
00250 }
00251 } else {
00252 nb = pack(buffer, sizeof(buffer), "Ss", 0);
00253 if(doWrite) write(buffer, nb);
00254 numbytes += nb;
00255 }
00256 }
00257 return numbytes;
00258 }
00259
00260 string COD::readStr()
00261 {
00262 static int r=0;
00263 r++;
00264 unsigned char buffer[66461];
00265 unsigned short int sz;
00266 read(buffer, 2);
00267 unpack(buffer, sizeof(buffer), "s", &sz);
00268
00269 read(buffer, sz);
00270 return string((char*)buffer, (unsigned int)sz);
00271 }
00272
00273 unsigned short int COD::readShort()
00274 {
00275 unsigned char buffer[2];
00276 read(buffer, 2);
00277 unsigned short int nt;
00278 unpack(buffer, sizeof(buffer), "s", &nt);
00279 return nt;
00280 }
00281
00282 unsigned long COD::readLong()
00283 {
00284 unsigned char buffer[4];
00285 read(buffer, 4);
00286 unsigned long nt;
00287 unpack(buffer, sizeof(buffer), "l", &nt);
00288 return nt;
00289 }
00290
00291 void COD::readObjectDesc(string& name, long& pos, deque<string>& types, MessageBlock& mb)
00292 {
00293 LOG("COD", 4, "about to read name");
00294 name = readStr();
00295
00296 LOG("COD", 4, "read name " << name);
00297
00298 pos = readLong();
00299
00300 LOG("COD", 4, "read pos " << pos);
00301
00302 short int nt = readShort();
00303 for(int n = 0; n < nt; n++) {
00304 string type = readStr();
00305 types.push_back(type);
00306 }
00307
00308 unsigned short int nm = readShort();
00309 for(int n = 0; n < nm; n++) {
00310 string method = readStr();
00311
00312 vRef<Message> msg = new Message();
00313 msg->setMethod(method);
00314
00315 unsigned short int nf = readShort();
00316 for(int m = 0; m < nf; m++) {
00317 string key = readStr();
00318 unsigned long vlen = readLong();
00319 char* b2 = (char*)malloc(vlen+1);
00320 read(b2, vlen);
00321 string data(b2, vlen);
00322 msg->insertField(-1, key, data, true);
00323 free(b2);
00324 }
00325
00326 mb.insertMessage(-1, &msg);
00327 }
00328 }
00329
00330 void COD::readObjectChildren(string& parent, deque<PCR>& children)
00331 {
00332 parent = readStr();
00333 unsigned long ch = readLong();
00334 for(unsigned int n = 0; n < ch; n++) {
00335 PCR p;
00336 p.context = readStr();
00337 p.child = readStr();
00338 children.push_back(p);
00339 }
00340 }
00341
00342 int COD::computeSize()
00343 {
00344 int numbytes = 14;
00345
00346 for(unsigned int i = 0; i < vobjectorder.size(); i++) {
00347 numbytes += writeObjectDesc(vobjectorder[i], false);
00348 }
00349
00350 for(unsigned int i = 0; i < vobjectorder.size(); i++) {
00351 if(vobjectorder[i]->vobject->getChildren().size() > 0 && vobjectorder[i]->savechildren) {
00352 numbytes += writeObjectChildren(vobjectorder[i]->vobject, false);
00353 }
00354 }
00355
00356 return numbytes;
00357 }
00358
00359 void COD::writeCOD(bool gzip)
00360 {
00361 if(f) {
00362 unsigned int size;
00363 writeCOD(&buffer, &size, gzip);
00364 f->write((char*)buffer, size);
00365 }
00366 }
00367
00368 void COD::write(const unsigned char* data, unsigned int size)
00369 {
00370 memcpy(buffer + offset, data, size);
00371 offset += size;
00372 }
00373
00374 void COD::write(const char* data, unsigned int size)
00375 {
00376 memcpy(buffer + offset, data, size);
00377 offset += size;
00378 }
00379
00380 void COD::read(unsigned char* data, unsigned int size)
00381 {
00382 if(f) {
00383 f->read((char*)data, size);
00384 if(f->eof()) throw eof();
00385 } else {
00386 if(offset + size > buffersize) throw eof();
00387 memcpy(data, buffer + offset, size);
00388 offset += size;
00389 }
00390 }
00391
00392 void COD::read(char* data, unsigned int size)
00393 {
00394 if(f) {
00395 f->read(data, size);
00396 if(f->eof()) throw eof();
00397 } else {
00398 if(offset + size > buffersize) throw eof();
00399 memcpy(data, buffer + offset, size);
00400 offset += size;
00401 }
00402 }
00403
00404 void COD::writeCOD(unsigned char** data, unsigned int* size, bool gzip)
00405 {
00406 if(buffer) free(buffer);
00407 *size = buffersize = computeSize() + 1;
00408 *data = buffer = (unsigned char*)malloc(buffersize + 1);
00409 offset = 0;
00410
00411 write("VOS", 4);
00412 char version[2] = {1, 0};
00413 write(version, 2);
00414
00415 unsigned char buf[16];
00416 write(buf, pack(buf, sizeof(buf), "l", vobjectorder.size()));
00417
00418 for(unsigned int i = 0; i < vobjectorder.size(); i++) {
00419 writeObjectDesc(vobjectorder[i]);
00420 }
00421
00422 unsigned long objsWithChildren = 0;
00423 for(unsigned int i = 0; i < vobjectorder.size(); i++) {
00424 if(vobjectorder[i]->vobject->getChildren().size() > 0 && vobjectorder[i]->savechildren) {
00425 objsWithChildren++;
00426 }
00427 }
00428
00429 write(buf, pack(buf, sizeof(buf), "l", objsWithChildren));
00430
00431 for(unsigned int i = 0; i < vobjectorder.size(); i++) {
00432 if(vobjectorder[i]->vobject->getChildren().size() > 0 && vobjectorder[i]->savechildren) {
00433 writeObjectChildren(vobjectorder[i]->vobject);
00434 }
00435 }
00436
00437 *size = offset;
00438
00439 if(gzip) {
00440 gzipCompress((unsigned char**)data, size, (const unsigned char*)buffer, offset);
00441 }
00442 }
00443
00444 void COD::readCOD(unsigned char* readfrom, unsigned int size)
00445 {
00446 buffer = readfrom;
00447 buffersize = size;
00448 offset = 0;
00449 readCOD();
00450 buffer = 0;
00451 buffersize = 0;
00452 }
00453
00454 bool COD::checkCOD()
00455 {
00456 unsigned char buf[66461];
00457
00458 read(buf, 4);
00459 if(!(buf[0] == 'V'
00460 && buf[1] == 'O'
00461 && buf[2] == 'S'
00462 && buf[3] == 0))
00463 {
00464 if(buf[0] == 31 && buf[1] == 139) {
00465 if(f) {
00466 string comp;
00467 comp.append((const char*)buf, 4);
00468 while(! f->eof()) {
00469 f->read((char*)buf, sizeof(buf));
00470 comp.append((const char*)buf, f->gcount());
00471 }
00472 gzipUncompress((unsigned char**)&buffer, &buffersize, (unsigned char*)comp.c_str(), (unsigned int)comp.size());
00473 } else {
00474 unsigned char* uncompressedbuffer;
00475 unsigned int uncompressedsize;
00476 gzipUncompress((unsigned char**)&uncompressedbuffer, &uncompressedsize, buffer, buffersize);
00477 buffer = uncompressedbuffer;
00478 buffersize = uncompressedsize;
00479 }
00480 iostream* oldf = f;
00481 f = 0;
00482 readCOD(buffer, buffersize);
00483 f = oldf;
00484 free(buffer);
00485 return false;
00486 } else {
00487 LOG("COD", 1, "This does not appear to be a COD file\n");
00488 return false;
00489 }
00490 }
00491 return true;
00492 }
00493
00494 void COD::readCOD()
00495 {
00496 if(! checkCOD()) return;
00497
00498 char version[2] = {0, 0};
00499 read(version, 2);
00500
00501
00502
00503 long numobjs = readLong();
00504
00505 map<string, string> fileToActual;
00506
00507 for(int i = 0; i < numobjs; i++) {
00508 deque<string> types;
00509 string name;
00510 vRef<MessageBlock> mb = new MessageBlock();
00511
00512 long pos;
00513 readObjectDesc(name, pos, types, *mb);
00514
00515 vRef<MetaObject> newvob = ls.createMetaObject(name.c_str(), types);
00516 fileToActual[name] = newvob->getName();
00517
00518 addVobject(&newvob, types, &mb, true);
00519
00520
00521 if(LocalProperty* lp = MetaObject::meta_cast<LocalProperty*>(&newvob)) {
00522 lp->initializeSecurity(ls);
00523 }
00524
00525 for(int n = 0; n < mb->numMessages(); n++) {
00526 vRef<Message> msg = mb->getMessage(n);
00527 msg->setType("message");
00528 msg->setTo(newvob->getURL().getString());
00529 msg->setFrom(ls.getURL().getString());
00530 newvob->sendMessage(&msg);
00531 }
00532 }
00533
00534 numobjs = readLong();
00535
00536 for(int i = 0; i < numobjs; i++) {
00537 string parent;
00538 deque<PCR> children;
00539
00540 readObjectChildren(parent, children);
00541 parent = fileToActual[parent];
00542
00543 Entry* e = vobjectTable[parent];
00544 if(! e) throw eof();
00545 e->savechildren = true;
00546
00547 LOG("COD", 4, "Looking for " << parent);
00548 vRef<Vobject::ParentChildRelation> pcr = ls.findChild(parent);
00549 LOG("COD", 4, "found it");
00550 for(unsigned int n = 0; n < children.size(); n++) {
00551 string cl = fileToActual[children[n].child];
00552 LOG("COD", 4, "Looking for " << cl << " (was " << children[n].child << ")");
00553 vRef<Vobject::ParentChildRelation> pcr2 = ls.findChild(cl);
00554 LOG("COD", 4, "found it");
00555 pcr->child->insertChild(-1, children[n].context, pcr2->child);
00556 }
00557 }
00558 }
00559
00560
00561 LocalSite& COD::getLocalSite()
00562 {
00563 ls.acquire();
00564 return ls;
00565 }
00566
00567 RemoteCOD::RemoteCOD(LocalSite& l, RemoteSite& r)
00568 : COD(l), rs(r)
00569 {
00570 rs.acquire();
00571 }
00572
00573 RemoteCOD::RemoteCOD(iostream& io, LocalSite& l, RemoteSite& r)
00574 : COD(io, l), rs(r)
00575 {
00576 rs.acquire();
00577 }
00578
00579 RemoteCOD::~RemoteCOD()
00580 {
00581 rs.release();
00582 }
00583
00584 void RemoteCOD::readCOD()
00585 {
00586 LOG("COD", 4, "Starting COD read");
00587
00588 if(! checkCOD()) return;
00589
00590 char version[2] = {0, 0};
00591 read(version, 2);
00592
00593 LOG("COD", 3, "File format version " << (int)version[0] << "." << (int)version[1]);
00594
00595 long numobjs = readLong();
00596
00597 LOG("COD", 4, "expecting " << numobjs << " objects");
00598
00599 double start, end, tot;
00600 start = getRealTime();
00601 for(int i = 0; i < numobjs; i++) {
00602 double start2, end2, tot2;
00603 start2 = getRealTime();
00604
00605 deque<string> types;
00606 string name;
00607 vRef<MessageBlock> mb = new MessageBlock();
00608
00609 long pos;
00610 readObjectDesc(name, pos, types, *mb);
00611
00612 LOG("COD", 4, "read child " << name);
00613
00614 vRef<Message> msg = new Message();
00615 msg->setType("update");
00616 msg->setMethod("core:set-child-update");
00617 msg->setFrom(rs.getURL().getString());
00618 msg->setSourceSite(&rs);
00619 msg->insertField(-1, "pos", (int)pos);
00620 msg->insertField(-1, "name", name);
00621 string path(rs.getURL().getString());
00622 path += "/";
00623 path += name;
00624 msg->insertField(-1, "path", path);
00625 if(types.size()) {
00626 for(unsigned int n = 0; n < types.size(); n++) {
00627 msg->insertField(-1, "type", types[n]);
00628 }
00629 } else msg->insertField(-1, "type", "");
00630 rs.sendUpdateMessage(&msg);
00631 vRef<Vobject::ParentChildRelation> newvob = rs.findChild(name);
00632
00633 addVobject(newvob->child, types, &mb, false);
00634
00635 for(int n = 0; n < mb->numMessages(); n++) {
00636 msg = mb->getMessage(n);
00637 msg->setType("update");
00638 msg->setFrom(path);
00639 msg->setSourceSite(&rs);
00640 LOG("COD", 4, "update to " << newvob->child->getURL().getString() << " is "
00641 << msg->getFormattedString());
00642 newvob->child->sendUpdateMessage(&msg);
00643 }
00644
00645 end2 = getRealTime();
00646 tot2 = end2 - start2;
00647 }
00648 end = getRealTime();
00649 tot = end - start;
00650
00651 LOG("COD", 4, "starting children read");
00652
00653 numobjs = readLong();
00654
00655 start = getRealTime();
00656 for(int i = 0; i < numobjs; i++) {
00657 string parent;
00658 deque<PCR> children;
00659
00660 readObjectChildren(parent, children);
00661
00662 vRef<Vobject::ParentChildRelation> newobj = rs.findChild(parent);
00663 vRef<Message> msg = new Message();
00664 msg->setType("update");
00665 msg->setMethod("core:set-child-update");
00666 msg->setFrom(rs.getURL().getString());
00667 msg->setSourceSite(&rs);
00668 for(unsigned int n = 0; n < children.size(); n++) {
00669 msg->insertField(-1, "pos", (int)n);
00670 msg->insertField(-1, "name", children[n].context);
00671 if(children[n].child.substr(0, 6) == "vop://") msg->insertField(-1, "path", children[n].child);
00672 else msg->insertField(-1, "path", rs.getURL().getString() + string("/") + children[n].child);
00673 }
00674 newobj->child->sendUpdateMessage(&msg);
00675 }
00676 end = getRealTime();
00677 tot = end - start;
00678 }
00679
00680 RemoteSite& RemoteCOD::getRemoteSite()
00681 {
00682 rs.acquire();
00683 return rs;
00684 }
00685
00686 int COD::pack(uint8_t *buf, int maxsize, char *fmt, ...)
00687 {
00688 va_list args;
00689 char* p;
00690 uint8_t* bp;
00691 uint8_t* st;
00692 uint16_t s, len;
00693 uint32_t l, i;
00694
00695 bp=buf;
00696 va_start(args, fmt);
00697 for(p=fmt; *p; p++)
00698 {
00699 switch(*p)
00700 {
00701 case 'c':
00702 if((bp - buf + 1) > maxsize) return -1;
00703
00704 *bp++ = (uint8_t)va_arg(args, int);
00705 break;
00706 case 's':
00707
00708 if((bp - buf + 4) > maxsize) return -1;
00709 s = (uint16_t)va_arg(args, int);
00710 *bp++ = s >> 8;
00711 *bp++ = s;
00712 break;
00713 case 'l':
00714 if((bp - buf + 4) > maxsize) return -1;
00715 l = (uint32_t)va_arg(args, uint32_t);
00716 *bp++ = l >> 24;
00717 *bp++ = l >> 16;
00718 *bp++ = l >> 8;
00719 *bp++ = l;
00720 break;
00721 case 'S':
00722 st = va_arg(args, uint8_t*);
00723 len = va_arg(args, int);
00724 if((bp - buf + 2 + len) > maxsize) return -1;
00725 *bp++ = len >> 8;
00726 *bp++ = len;
00727 for(i = 0; i < len; i++)
00728 *bp++ = *st++;
00729 break;
00730 case 'f':
00731 {
00732 if((bp - buf + 4) > maxsize) return -1;
00733 float f = (float)va_arg(args, double);
00734 uint32_t zz = *((uint32_t*)&f);
00735 *bp++ = zz >> 24;
00736 *bp++ = zz >> 16;
00737 *bp++ = zz >> 8;
00738 *bp++ = zz;
00739 break;
00740 }
00741 default:
00742 va_end(args);
00743 return -1;
00744 }
00745 }
00746 va_end(args);
00747 return (bp - buf);
00748 }
00749
00750 int COD::unpack(const uint8_t *buf, int maxsize, char *fmt, ...)
00751 {
00752 va_list args;
00753 char* p;
00754 const uint8_t* bp;
00755 uint8_t* pc;
00756 uint16_t* ps;
00757 uint32_t* pl;
00758 uint8_t** st;
00759 int len, i;
00760
00761 bp=buf;
00762 va_start(args, fmt);
00763 for(p=fmt; *p; p++)
00764 {
00765 switch(*p)
00766 {
00767 case 'c':
00768 if(bp - buf + 1 > maxsize) return -1;
00769 pc = va_arg(args, uint8_t*);
00770 *pc = *bp++;
00771 break;
00772 case 's':
00773 if(bp - buf + 2 > maxsize) return -1;
00774 ps = va_arg(args, uint16_t*);
00775 *ps = *bp++ << 8;
00776 *ps |= *bp++;
00777 break;
00778 case 'l':
00779 if(bp - buf + 4 > maxsize) return -1;
00780 pl = va_arg(args, uint32_t*);
00781 *pl = *bp++ << 24;
00782 *pl |= *bp++ << 16;
00783 *pl |= *bp++ << 8;
00784 *pl |= *bp++;
00785 break;
00786 case 'S':
00787 st = va_arg(args, uint8_t**);
00788 pl = va_arg(args, uint32_t*);
00789 if(bp - buf + 2 > maxsize) return -1;
00790 len = *bp++ << 8;
00791 len |= *bp++;
00792 if(bp - buf + len > maxsize) return -1;
00793 *pl = len;
00794 *st = (uint8_t*)malloc(len+1);
00795 for(i = 0; i < len; i++)
00796 (*st)[i] = *bp++;
00797 (*st)[i] = 0;
00798 break;
00799 case 'f':
00800 {
00801 if(bp - buf + 4 > maxsize) return -1;
00802 float* f = va_arg(args, float*);
00803 uint32_t l = *bp++ << 24;
00804 l |= *bp++ << 16;
00805 l |= *bp++ << 8;
00806 l |= *bp++;
00807 *f = *((float*)&l);
00808 break;
00809 }
00810 default:
00811 va_end(args);
00812 return -1;
00813 }
00814 }
00815 va_end(args);
00816 return bp - buf;
00817 }
00818
00819 void COD::gzipCompress(unsigned char** dest, unsigned int* destlen, const unsigned char* source, unsigned int srclen)
00820 {
00821 *destlen = srclen + (srclen/1000) + 13 + 18;
00822 *dest = (unsigned char*)malloc(*destlen);
00823
00824 int t = time(0);
00825
00826
00827
00828
00829 (*dest)[0] = 31;
00830 (*dest)[1] = 139;
00831 (*dest)[2] = 8;
00832 (*dest)[3] = 0;
00833 (*dest)[4] = t & 0xFF;
00834 (*dest)[5] = (t >> 8) & 0xFF;
00835 (*dest)[6] = (t >> 16) & 0xFF;
00836 (*dest)[7] = (t >> 24) & 0xFF;
00837 (*dest)[8] = 0;
00838 (*dest)[9] = 255;
00839
00840 z_stream st;
00841 st.next_in = (Bytef*)source;
00842 st.avail_in = srclen;
00843 st.total_in = 0;
00844
00845 st.next_out = (Bytef*)(*dest + 10);
00846 st.avail_out = *destlen;
00847 st.total_out = 0;
00848
00849 st.zalloc = 0;
00850 st.zfree = 0;
00851
00852 deflateInit2(&st, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
00853 if(deflate(&st, Z_FINISH) != Z_STREAM_END) {
00854 throw eof();
00855 }
00856 deflateEnd(&st);
00857 *destlen = st.total_out;
00858
00859 int crc = crc32(0, (const Bytef*)source, srclen);
00860 (*dest)[10 + *destlen + 0] = crc & 0xFF;
00861 (*dest)[10 + *destlen + 1] = (crc >> 8) & 0xFF;
00862 (*dest)[10 + *destlen + 2] = (crc >> 16) & 0xFF;
00863 (*dest)[10 + *destlen + 3] = (crc >> 24) & 0xFF;
00864 (*dest)[10 + *destlen + 4] = srclen & 0xFF;
00865 (*dest)[10 + *destlen + 5] = (srclen >> 8) & 0xFF;
00866 (*dest)[10 + *destlen + 6] = (srclen >> 16) & 0xFF;
00867 (*dest)[10 + *destlen + 7] = (srclen >> 24) & 0xFF;
00868
00869 *destlen += 18;
00870 }
00871
00872 void COD::gzipUncompress(unsigned char** dest, unsigned int* destlen, const unsigned char* source, unsigned int srclen)
00873 {
00874 unsigned int len = 0;
00875 unsigned int crc = 0;
00876
00877 len = source[srclen-4]
00878 | (source[srclen-3] << 8)
00879 | (source[srclen-2] << 16)
00880 | (source[srclen-1] << 24);
00881
00882 crc = source[srclen-8]
00883 | (source[srclen-7] << 8)
00884 | (source[srclen-6] << 16)
00885 | (source[srclen-5] << 24);
00886
00887 *destlen = len;
00888 *dest = (unsigned char*)malloc(*destlen);
00889
00890
00891
00892
00893 if(source[0] != 31 || source[1] != 139 || source[2] != 8) throw eof();
00894
00895 int offset = 10;
00896
00897 #define FTEXT 0x01
00898 #define FHCRC 0x02
00899 #define FEXTRA 0x04
00900 #define FNAME 0x08
00901 #define FCOMMENT 0x10
00902 #define FRESERVED (0x20 | 0x40 | 0x80)
00903
00904 if(source[3] & FRESERVED) throw eof();
00905
00906 if(source[3] & FEXTRA) {
00907 int skip = 0;
00908 skip = source[offset] | (source[offset+1] << 8);
00909 offset += 2 + skip;
00910 }
00911
00912 if(source[3] & FNAME) {
00913 while(source[offset]) offset++;
00914 offset++;
00915 }
00916
00917 if(source[3] & FCOMMENT) {
00918 while(source[offset]) offset++;
00919 offset++;
00920 }
00921
00922 if(source[3] & FHCRC) {
00923 offset += 2;
00924 }
00925
00926 z_stream st;
00927 st.next_in = (Bytef*)source + offset;
00928 st.avail_in = srclen;
00929 st.total_in = 0;
00930
00931 st.next_out = (Bytef*)(*dest);
00932 st.avail_out = *destlen;
00933 st.total_out = 0;
00934
00935 st.zalloc = 0;
00936 st.zfree = 0;
00937
00938 inflateInit2(&st, -MAX_WBITS);
00939 if(inflate(&st, Z_FINISH) != Z_STREAM_END) {
00940 throw eof();
00941 }
00942 inflateEnd(&st);
00943 *destlen = st.total_out;
00944
00945 if(crc32(0, (const Bytef*)*dest, *destlen) != crc) {
00946 free(*dest);
00947 throw eof();
00948 }
00949 }