예제 #1
0
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;
}
예제 #2
0
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;
}