コード例 #1
0
ファイル: HEPDao.cpp プロジェクト: dreamsxin/sipXhomer
// NOTE: This is not the most elegant code however, some concessions were made to
// make this as fast as possible as you could get hundreds of inserts per second
void HEPDao::save(StateQueueMessage& object)
{
  int outgoing = 0;
  int ipProtoId = HEPMessage::TCP;
  std::string ip4SrcAddress;
  std::string ip4DestAddress;
  int srcPort = 0;
  int destPort = 0;
  double timeStamp = 0;
  double timeStampMicroOffset = 0;
  std::string data;

  if (!object.get("Outgoing", outgoing))
    return;

#if 0 //  For now we determine this using the VIA header since the sipstack
      //  does not include the transport type in the processor callback
  if (!object.get("IpProtoId", ipProtoId))
    return;
#endif

  if (!object.get("Ip4SrcAddress", ip4SrcAddress))
    return;

  if (!object.get("Ip4DestAddress", ip4DestAddress))
    return;

  if (!object.get("SrcPort", srcPort))
    return;

  if (!object.get("DestPort", destPort))
    return;

  if (!object.get("TimeStamp", timeStamp))
    return;

  if (!object.get("TimeStampMicroOffset", timeStampMicroOffset))
    return;

  if (!object.get("Data", data))
    return;


  Data buffer(data.c_str());

  SipMessage* msg = SipMessage::make(buffer);

  if (!msg)
    return;

  if (msg->isInvalid())
  {
    delete msg;
    return;
  }

  SQLRETURN err = SQLFreeStmt(mInsert, SQL_UNBIND);
  checkError(err, mInsert, SQL_HANDLE_STMT);
  mFieldIndex = 0;

  struct timeval now;
  now.tv_sec = timeStamp;
  now.tv_usec = timeStampMicroOffset;
  time_t timeNow = now.tv_sec;
  struct tm* gmt = gmtime (&timeNow);

  // date
  TIMESTAMP_STRUCT date;
  date.year = gmt->tm_year + 1900;
  date.month = gmt->tm_mon + 1;
  date.day = gmt->tm_mday;
  date.hour = gmt->tm_hour;
  date.minute = gmt->tm_min;
  date.second = gmt->tm_sec;
  date.fraction = 0;
  bind(DATE, &date, sizeof(date));

  // micro_ts
  unsigned long long microTs = (unsigned long long)now.tv_sec*1000000+now.tv_usec;
  bind(MICRO_TS, &microTs, sizeof(unsigned long long));


  // method
  std::string cseqMethod;
  if (msg->exists(h_CSeq))
  {
    switch(msg->const_header(h_CSeq).method())
    {
    case ACK:
      cseqMethod = "ACK";
      break;
    case BYE:
      cseqMethod = "BYE";
      break;
    case CANCEL:
      cseqMethod = "CANCEL";
      break;
    case INVITE:
      cseqMethod = "INVITE";
      break;
    case NOTIFY:
      cseqMethod = "NOTIFY";
      break;
    case OPTIONS:
      cseqMethod = "OPTIONS";
      break;
    case REFER:
      cseqMethod = "REFER";
      break;
    case REGISTER:
      cseqMethod = "REGISTER";
      break;
    case SUBSCRIBE:
      cseqMethod = "SUBSCRIBE";
      break;
    case MESSAGE:
      cseqMethod = "MESSAGE";
      break;
    case INFO:
      cseqMethod = "INFO";
      break;
    case PRACK:
      cseqMethod = "PRACK";
      break;
    case PUBLISH:
      cseqMethod = "PUBLISH";
      break;
    case SERVICE:
      cseqMethod = "SERVICE";
      break;
    case UPDATE:
      cseqMethod = "UPDATE";
      break;
    default:
      cseqMethod = "????";
      break;
    }
    bind(METHOD, (void *) cseqMethod.data(), cseqMethod.length());
  }

  if (!msg->isRequest())
  {
    // reply_reason
    std::string reply_reason;
    if (msg->exists(h_Reasons))
    {
      reply_reason = msg->const_header(h_Reasons).front().value().c_str();
      bind(REPLY_REASON, (void *) reply_reason.data(), reply_reason.length());
    }
  }

  std::string requestLine;
  std::string statusLine;
  std::string requestUriUser;

  const char* direction = outgoing ? "Outgoing" : "Incoming";

  if (msg->isRequest())
  {
    // ruri
    std::ostringstream strm;
    msg->const_header(h_RequestLine).uri().encode(strm);
    requestLine = strm.str();
    bind(REQUESTURI, (void *) requestLine.data(), requestLine.length());

    // ruri_user
    requestUriUser = msg->const_header(h_RequestLine).uri().user().c_str();
    bind(REQUESTURI_USER, (void *) requestUriUser.data(), requestUriUser.length());

    OS_LOG_INFO(FAC_NET, "HEPDao::save " << direction << ": " << cseqMethod << " "
            << ip4SrcAddress << ":" << srcPort << "->"
            << ip4DestAddress << ":" << destPort );
  }
  else
  {
    std::ostringstream strm;
    msg->const_header(h_StatusLine).encode(strm);
    statusLine = strm.str();  // where does this go
    OS_LOG_INFO(FAC_NET, "HEPDao::save " << direction << ": " << statusLine << " "
            << ip4SrcAddress << ":" << srcPort << "->"
            << ip4DestAddress << ":" << destPort);
  }

  OS_LOG_DEBUG(FAC_NET, "HEPDao::save SIP Message " << data.c_str());

  std::string fromTag;
  std::string fromUser;
  if (msg->exists(h_From))
  {
    // from_user
    fromUser = msg->const_header(h_From).uri().user().c_str();
    bind(FROM_USER, (void *) fromUser.data(), fromUser.length());

    // from_tag
    fromTag = msg->const_header(h_From).exists(p_tag) ? msg->const_header(h_From).param(p_tag).c_str()
        : std::string();
    bind(FROM_TAG, (void *) fromTag.data(), fromTag.length());
  }

  std::string toTag;
  std::string toUser;
  if (msg->exists(h_To))
  {
    // to_user
    toUser = msg->const_header(h_To).uri().user().c_str();
    bind(TO_USER, (void *) toUser.data(), toUser.length());

    // to_tag
    toTag = msg->const_header(h_To).exists(p_tag) ? msg->const_header(h_To).param(p_tag).c_str()
        : std::string();
    bind(TO_TAG, (void *) toTag.data(), toTag.length());
  }

  // pid_user
  std::string pidentity;
  if (msg->exists(h_PAssertedIdentities))
  {
    std::ostringstream pidStrm;
    msg->const_header(h_PAssertedIdentities).front().uri().encode(pidStrm);
    pidentity = pidStrm.str();
    bind(PID_USER, (void *) pidentity.data(), pidentity.length());
  }

  std::string contactUser;
  std::string contactHost;
  int contactPort = 0;
  if (msg->exists(h_Contacts))
  {
    // contact_user
    contactUser = msg->const_header(h_Contacts).front().uri().user().c_str();
    bind(CONTACT_USER, (void *) contactUser.data(), contactUser.length());

    //contact_ip
    contactHost = msg->const_header(h_Contacts).front().uri().host().c_str();
    bind(CONTACT_IP, (void *) contactHost.data(), contactHost.length());

    //contact_port
    contactPort = msg->const_header(h_Contacts).front().uri().port();
    bind(CONTACT_PORT, (void *) &contactPort, sizeof(contactPort));
  }
  else
  {
    //
    // There is no contact but homer requires it cant be null
    //
    // contact_user
    bind(CONTACT_USER, (void *) contactUser.data(), contactUser.length());
    //contact_ip
    bind(CONTACT_IP, (void *) contactHost.data(), contactHost.length());
    //contact_port
    bind(CONTACT_PORT, (void *) &contactPort, sizeof(contactPort));
  }

  // auth_user

  // callid
  std::string callId;
  if (msg->exists(h_CallID))
  {
    callId = msg->const_header(h_CallID).value().c_str();
    bind(CALL_ID, (void *) callId.data(), callId.length());
  }

  // callid_aleg

  std::string viaBranch;
  std::string via;
  std::string viaProtocol;
  if (msg->exists(h_Vias))
  {
    // via_1
    Via& frontVia = msg->header(h_Vias).front();
    std::ostringstream viaStrm;
    frontVia.encode(viaStrm);
    via = viaStrm.str();
    bind(VIA_1, (void *) via.data(), via.length());

    // via_1_branch
    if (frontVia.param(p_branch).hasMagicCookie())
      viaBranch = "z9hG4bK";
    viaBranch += frontVia.param(p_branch).getTransactionId().c_str();
    bind(VIA_1_BRANCH, (void *) viaBranch.data(), viaBranch.length());

    //
    // Get the protocol string to be used for determining the transport type
    //
    viaProtocol = frontVia.protocolName().data();
    boost::to_upper(viaProtocol);
  }


  // cseq
  std::string cseq;
  std::ostringstream cseqStrm;
  if (msg->exists(h_CSeq))
  {
    msg->const_header(h_CSeq).encode(cseqStrm);
    cseq = cseqStrm.str();
    bind(CSEQ, (void *) cseq.data(), cseq.length());
  }

  // diversion

  if (msg->isRequest())
  {
    // reason
    std::string reason;
    if (msg->exists(h_Reasons))
    {
      reason = msg->const_header(h_Reasons).front().value().c_str();
      bind(REPLY_REASON, (void *) reason.data(), reason.length());
    }
  }

  // content_type
  std::string contentType;
  if (msg->exists(h_ContentType))
  {
    std::ostringstream ctypeStrm;
    msg->const_header(h_ContentType).encode(ctypeStrm);
    contentType = ctypeStrm.str();
    bind(CONTENT_TYPE, (void *) contentType.data(), contentType.length());
  }

  // authorization
  std::string authorization;
  if (msg->exists(h_Authorizations))
  {
    std::ostringstream authStrm;
    msg->const_header(h_Authorizations).front().encode(authStrm);
    authorization = authStrm.str();
    bind(AUTH, (void *) authorization.data(), authorization.length());
  }
  else if (msg->exists(h_ProxyAuthorizations))
  {
    std::ostringstream authStrm;
    msg->const_header(h_ProxyAuthorizations).front().encode(authStrm);
    authorization = authStrm.str();
    bind(AUTH, (void *) authorization.data(), authorization.length());
  }

  // user_agent
  std::string userAgent;
  if (msg->exists(h_UserAgent))
  {
    userAgent = msg->const_header(h_UserAgent).value().c_str();
    bind(USER_AGENT, (void *) userAgent.data(), userAgent.length());
  }

  // source_ip
  bind(SOURCE_IP, (void *) ip4SrcAddress.c_str(), ip4SrcAddress.length());

  // source_port
  bind(SOURCE_PORT, (void*)&srcPort, sizeof(srcPort));

  // destination_ip
  bind(DEST_IP, (void *) ip4DestAddress.c_str(), ip4DestAddress.length());

  // destination_port
  bind(DEST_PORT, (void*)&destPort, sizeof(destPort));

  // originator_ip

  // originator_port
  int zero = 0;
  bind(ORIGINATOR_PORT, (void*)&zero, sizeof(zero));

  // proto
  if (!viaProtocol.empty())
  {
    if (viaProtocol == "TCP")
      ipProtoId = HEPMessage::TCP;
    else
      ipProtoId= HEPMessage::UDP;
  }
  bind(PROTO, (void*)&ipProtoId, sizeof(ipProtoId));

  // family
  // only field in schema allowed to be NULL
  int protoFamily = HEPMessage::IpV4;
  bind(FAMILY, (void*)&protoFamily, sizeof(protoFamily));

  // rtp_stat

  // type
  int protocolType = HEPMessage::SipX;
  bind(TYPE, (void*)&protocolType, sizeof(protocolType));
  // node

  // NOTE: Need to always bind last column or you get SQL unbound cols error

  // msg
  bind(MSG, (void *) data.c_str(), data.length());

  err = SQLExecute(mInsert);
  checkError(err, mInsert, SQL_HANDLE_STMT);

  delete msg;
}