int parse_message (char *message, unsigned int blen, unsigned int *bytes_parsed, sip_msg_t * psip, unsigned int type) { unsigned int new_len = blen; int header_offset = 0; char *pch, *ped; //bool allowRequest = FALSE; bool allowPai = FALSE; bool parseVIA = FALSE; bool parseContact = FALSE; if (blen <= 2) return 0; int offset = 0, last_offset = 0; char *c, *tmp; c = message; /* Request/Response line */ for (; *c && c - message < new_len; c++) { if (*c == '\n' && *(c - 1) == '\r') { offset = (c + 1) - message; break; } } if (offset == 0) { // likely Sip Message Body only... *bytes_parsed = c - message; return 0; } psip->responseCode = 0; tmp = (char *) message; if (!memcmp ("SIP/2.0 ", tmp, 8)) { psip->responseCode = atoi (tmp + 8); psip->isRequest = FALSE; // Extract Response code's reason char *reason = tmp + 12; for (; *reason; reason++) { if (*reason == '\n' && *(reason - 1) == '\r') { break; } } psip->reason.s = tmp + 12; psip->reason.len = reason - (tmp + 13); } else { psip->isRequest = TRUE; if (!memcmp (tmp, INVITE_METHOD, INVITE_LEN)) { psip->methodType = INVITE; //allowRequest = TRUE; allowPai = TRUE; } else if (!memcmp (tmp, ACK_METHOD, ACK_LEN)) psip->methodType = ACK; else if (!memcmp (tmp, BYE_METHOD, BYE_LEN)) psip->methodType = BYE; else if (!memcmp (tmp, CANCEL_METHOD, CANCEL_LEN)) psip->methodType = CANCEL; else if (!memcmp (tmp, OPTIONS_METHOD, OPTIONS_LEN)) psip->methodType = OPTIONS; else if (!memcmp (tmp, REGISTER_METHOD, REGISTER_LEN)) psip->methodType = REGISTER; else if (!memcmp (tmp, PRACK_METHOD, PRACK_LEN)) psip->methodType = PRACK; else if (!memcmp (tmp, SUBSCRIBE_METHOD, SUBSCRIBE_LEN)) psip->methodType = SUBSCRIBE; else if (!memcmp (tmp, NOTIFY_METHOD, NOTIFY_LEN)) psip->methodType = NOTIFY; else if (!memcmp (tmp, PUBLISH_METHOD, PUBLISH_LEN)) { psip->methodType = PUBLISH; /* we need via and contact */ if (type == 2) { parseVIA = TRUE; parseContact = TRUE; //allowRequest = TRUE; } } else if (!memcmp (tmp, INFO_METHOD, INFO_LEN)) psip->methodType = INFO; else if (!memcmp (tmp, REFER_METHOD, REFER_LEN)) psip->methodType = REFER; else if (!memcmp (tmp, MESSAGE_METHOD, MESSAGE_LEN)) psip->methodType = MESSAGE; else if (!memcmp (tmp, UPDATE_METHOD, UPDATE_LEN)) psip->methodType = UPDATE; else { psip->methodType = UNKNOWN; } if ((pch = strchr (tmp + 1, ' ')) != NULL) { psip->methodString.s = tmp; psip->methodString.len = (pch - tmp); if ((ped = strchr (pch + 1, ' ')) != NULL) { psip->requestURI.s = pch + 1; psip->requestURI.len = (ped - pch - 1); LDEBUG ("INVITE RURI: %.*s\n", psip->requestURI.len, psip->requestURI.s); /* extract user */ getUser (&psip->ruriUser, &psip->ruriDomain, psip->requestURI.s, psip->requestURI.len); } } } c = message + offset; int contentLength = 0; for (; *c && c - message < new_len; c++) { /* END of Request line and START of all other headers */ if (*c == '\r' && *(c + 1) == '\n') { /* end of this line */ last_offset = offset; offset = (c + 2) - message; tmp = (message + last_offset); /* BODY */ if (contentLength > 0 && (offset - last_offset) == 2) { if (psip->hasSdp) { parseSdp (c, psip); } else if (psip->hasVqRtcpXR) { parseVQRtcpXR (c, psip); } break; } if ((*tmp == 'i' && *(tmp + 1) == ':') || ((*tmp == 'C' || *tmp == 'c') && (*(tmp + 5) == 'I' || *(tmp + 5) == 'i') && *(tmp + CALLID_LEN) == ':')) { if (*(tmp + 1) == ':') header_offset = 1; else header_offset = CALLID_LEN; set_hname (&psip->callId, (offset - last_offset - CALLID_LEN), tmp + CALLID_LEN); continue; } /* Content-Length */ if ((*tmp == 'l' && *(tmp + 1) == ':') || ((*tmp == 'C' || *tmp == 'c') && (*(tmp + 8) == 'L' || *(tmp + 8) == 'l') && *(tmp + CONTENTLENGTH_LEN) == ':')) { if (*(tmp + 1) == ':') header_offset = 1; else header_offset = CONTENTLENGTH_LEN; contentLength = atoi (tmp + header_offset + 1); continue; } else if ((*tmp == 'C' || *tmp == 'c') && (*(tmp + 1) == 'S' || *(tmp + 1) == 's') && *(tmp + CSEQ_LEN) == ':') { set_hname (&psip->cSeq, (offset - last_offset - CSEQ_LEN), tmp + CSEQ_LEN); splitCSeq (psip, psip->cSeq.s, psip->cSeq.len); } /* content type Content-Type: application/sdp CONTENTTYPE_LEN */ else if (((*tmp == 'C' || *tmp == 'c') && (*(tmp + 7) == '-') && (*(tmp + 8) == 't' || *(tmp + 8) == 'T') && *(tmp + CONTENTTYPE_LEN) == ':')) { if (*(tmp + CONTENTTYPE_LEN + 1) == ' ') header_offset = 14; else header_offset = 13; if (!strncmp ((tmp + CONTENTTYPE_LEN + header_offset), "vq-rtcpxr", 9)) { psip->hasVqRtcpXR = TRUE; } else if (!memcmp ((tmp + CONTENTTYPE_LEN + header_offset), "sdp", 3)) { psip->hasSdp = TRUE; } continue; } else if (parseVIA && ((*tmp == 'V' || *tmp == 'v') && (*(tmp + 1) == 'i' || *(tmp + 1) == 'i') && *(tmp + VIA_LEN) == ':')) { set_hname (&psip->via, (offset - last_offset - VIA_LEN), tmp + VIA_LEN); continue; } else if (parseContact && ((*tmp == 'm' && *(tmp + 1) == ':') || ((*tmp == 'C' || *tmp == 'c') && (*(tmp + 5) == 'C' || *(tmp + 5) == 'c') && *(tmp + CONTACT_LEN) == ':'))) { if (*(tmp + 1) == ':') header_offset = 1; else header_offset = CONTACT_LEN; set_hname (&psip->contactURI, (offset - last_offset - header_offset), tmp + header_offset); continue; } else if ((*tmp == 'f' && *(tmp + 1) == ':') || ((*tmp == 'F' || *tmp == 'f') && (*(tmp + 3) == 'M' || *(tmp + 3) == 'm') && *(tmp + FROM_LEN) == ':')) { if (*(tmp + 1) == ':') header_offset = 1; else header_offset = FROM_LEN; set_hname (&psip->fromURI, (offset - last_offset - FROM_LEN), tmp + FROM_LEN); psip->hasFrom = TRUE; if (!psip->fromURI.len == 0 && getTag (&psip->fromTag, psip->fromURI.s, psip->fromURI.len)) { psip->hasFromTag = TRUE; } /* extract user */ getUser (&psip->fromUser, &psip->fromDomain, psip->fromURI.s, psip->fromURI.len); continue; } else if ((*tmp == 't' && *(tmp + 1) == ':') || ((*tmp == 'T' || *tmp == 't') && *(tmp + TO_LEN) == ':')) { if (*(tmp + 1) == ':') header_offset = 1; else header_offset = TO_LEN; if (set_hname (&psip->toURI, (offset - last_offset - header_offset), tmp + header_offset)) { psip->hasTo = TRUE; if (!psip->toURI.len == 0 && getTag (&psip->toTag, psip->toURI.s, psip->toURI.len)) { psip->hasToTag = TRUE; } /* extract user */ getUser (&psip->toUser, &psip->toDomain, psip->toURI.s, psip->toURI.len); } continue; } if (allowPai) { if (((*tmp == 'P' || *tmp == 'p') && (*(tmp + 2) == 'P' || *(tmp + 2) == 'p') && (*(tmp + 13) == 'i' || *(tmp + 13) == 'I') && *(tmp + PPREFERREDIDENTITY_LEN) == ':')) { set_hname (&psip->pidURI, (offset - last_offset - PPREFERREDIDENTITY_LEN), tmp + PPREFERREDIDENTITY_LEN); psip->hasPid = TRUE; /* extract user */ getUser (&psip->paiUser, &psip->paiDomain, psip->pidURI.s, psip->pidURI.len); continue; } else if (((*tmp == 'P' || *tmp == 'p') && (*(tmp + 2) == 'A' || *(tmp + 2) == 'a') && (*(tmp + 13) == 'i' || *(tmp + 13) == 'I') && *(tmp + PASSERTEDIDENTITY_LEN) == ':')) { set_hname (&psip->pidURI, (offset - last_offset - PASSERTEDIDENTITY_LEN), tmp + PASSERTEDIDENTITY_LEN); psip->hasPid = TRUE; /* extract user */ getUser (&psip->paiUser, &psip->paiDomain, psip->pidURI.s, psip->pidURI.len); continue; } } } } return 1; }
int CFileSystem::validatePool(const std::string& path) { if(!directoryExists(path)) { LOG_ERROR("Pool directory doesn't exist: %s", path.c_str()); return 0; } int res=0; std::list <std::string>dirs; dirs.push_back(path); int maxdirs=257; //FIXME: unknown dirs in pool will break bar int finished=0; IHash* md5=new HashMD5(); while(!dirs.empty()) { struct dirent* dentry; DIR* d; const std::string dir=dirs.front(); dirs.pop_front(); d=opendir(dir.c_str()); while ( (dentry=readdir(d))!=NULL) { LOG_PROGRESS(finished, maxdirs); std::string absname=dir; absname += PATH_DELIMITER; absname += dentry->d_name; if (dentry->d_name[0]!='.') { //don't check hidden files / . / .. #ifndef WIN32 if ((dentry->d_type & DT_DIR)!=0) { //directory #else struct stat sb; stat(absname.c_str(), &sb); if((sb.st_mode & S_IFDIR)!=0) { #endif dirs.push_back(absname); } else { FileData filedata=FileData(); int len=absname.length(); if (len<36) { //file length has at least to be <md5[0]><md5[1]>/<md5[2-30]>.gz LOG_ERROR("Invalid file: %s", absname.c_str()); } else { std::string md5str=""; md5str.push_back(absname.at(len-36)); //get md5 from path + filename md5str.push_back(absname.at(len-35)); md5str.append(absname.substr(len-33, 30)); md5->Set(md5str); for(unsigned i=0; i<16; i++) { filedata.md5[i]=md5->get(i); } if (!fileIsValid(&filedata, absname)) { //check if md5 in filename is the same as in filename LOG_ERROR("Invalid File in pool: %s",absname.c_str()); } else { res++; } } } } } finished++; closedir(d); } delete md5; LOG_PROGRESS(finished, maxdirs, true); LOG(""); return res; } bool CFileSystem::isOlder(const std::string& filename, int secs) { struct stat sb; if (stat(filename.c_str(),&sb)<0) { return true; } time_t t; #ifdef WIN32 SYSTEMTIME pTime; FILETIME pFTime; GetSystemTime(&pTime); SystemTimeToFileTime(&pTime, &pFTime); t = FiletimeToTimestamp(pFTime); #else time(&t); #endif LOG_DEBUG("%s is %d seconds old, redownloading at %d",filename.c_str(), (int)(t - sb.st_ctime), secs); return (t<sb.st_ctime+secs); } bool CFileSystem::fileExists(const std::string& filename) { struct stat buffer; return stat(filename.c_str(), &buffer) == 0; } bool CFileSystem::parseTorrent(const char* data, int size, IDownload* dl) { struct be_node* node=be_decoden(data, size); //#ifdef DEBUG // be_dump(node); //#endif if(node==NULL) { LOG_ERROR("couldn't parse torrent"); return false; } if (node->type!=BE_DICT) { LOG_ERROR("Error in torrent data"); be_free(node); return false; } int i; struct be_node* infonode=NULL; for (i = 0; node->val.d[i].val; ++i) { //search for a dict with name info if ((node->type==BE_DICT) && (strcmp(node->val.d[i].key,"info")==0)) { infonode=node->val.d[i].val; break; } } if (infonode==NULL) { LOG_ERROR("couldn't find info node in be dict"); be_free(node); return false; } for (i = 0; infonode->val.d[i].val; ++i) { //fetch needed data from dict and fill into dl struct be_node*datanode; datanode=infonode->val.d[i].val; switch(datanode->type) { case BE_STR: //current value is a string if ((strcmp("name",infonode->val.d[i].key)==0) && (dl->name.empty())) { //set filename if not already set dl->name=datanode->val.s; } else if (!strcmp("pieces", infonode->val.d[i].key)) { //hash sum of a piece const int count = be_str_len(datanode)/20; //one sha1 sum is 5 * 4 bytes long for (int i=0; i<count; i++) { struct IDownload::piece piece; const unsigned char* data=(unsigned char*)&datanode->val.s[i*20]; piece.sha=new HashSHA1(); if (!piece.sha->Set(data, 20)) { LOG_ERROR("Error setting sha1"); } piece.state=IDownload::STATE_NONE; dl->pieces.push_back(piece); } } break; case BE_INT: //current value is a int if (strcmp("length",infonode->val.d[i].key)==0) { //filesize dl->size=datanode->val.i; } else if (!strcmp("piece length",infonode->val.d[i].key)) { //length of a piece dl->piecesize=datanode->val.i; LOG_DEBUG("dl->piecesize: %d", dl->piecesize); } break; default: break; } } LOG_DEBUG("Parsed torrent data: %s %d", dl->name.c_str(), dl->piecesize); be_free(node); return true; } bool CFileSystem::dumpSDP(const std::string& filename) { std::list<FileData*> files; files.clear(); if (!parseSdp(filename, files)) return false; LOG_INFO("md5 (filename in pool) crc32 size filename"); std::list<FileData*>::iterator it; HashMD5 md5; for(it=files.begin(); it!=files.end(); ++it) { md5.Set((*it)->md5, sizeof((*it)->md5)); LOG_INFO("%s %.8X %8d %s",md5.toString().c_str(), (*it)->crc32, (*it)->size, (*it)->name.c_str()); } return true; }