Exemple #1
0
/*
* Example obtainting client stats from an E_CONNECT or E_STOP event 
*/
void FmsAuthAdaptor::processStats(IFmsAuthEvent* pAev)
{
	 I64 statsHandle;
	 FmsClientStats baseStats;
	 if (!getI64Field(pAev, IFmsAuthEvent::F_CLIENT_STATS_HANDLE, statsHandle))
		 return;
	 char* pAppName = getStringField(pAev, IFmsAuthEvent::F_APP_NAME);
	 if (pAev->getType() == IFmsAuthEvent::E_CONNECT) 
	 {
		 getStats(statsHandle, baseStats);

		 // log data
		 char buf[1024];
		 char hashKey[9];
		 memset(hashKey, 0, 9);
		 memcpy(hashKey, &statsHandle, sizeof(statsHandle));
		 sprintf(buf, "client Stats Handle= %s, bytes_in= %f, bytes_out= %f\n", hashKey, 
			 static_cast<double>(baseStats.bytes_in), static_cast<double>(baseStats.bytes_out));
		 m_pFmsAuthServerContext->log(buf, IFmsServerContext::kInformation, false); 
	 }
	 else if (pAev->getType() == IFmsAuthEvent::E_STOP)
	 {
		 getStats(statsHandle, baseStats);
	 }
}
COLORREF CppSQLite3Query::getColorField(int nField, COLORREF crNullValue /*= 0*/)
{
    CString str = getStringField(nField);
	if (str.IsEmpty())
	{
		return crNullValue;
	}
	else
	{
		return WizStringToColor(str);
	}
}
void DatabasesCloner::_setAdminAsFirst(std::vector<BSONElement>& dbsArray) {
    auto adminIter = std::find_if(dbsArray.begin(), dbsArray.end(), [](BSONElement elem) {
        if (!elem.isABSONObj()) {
            return false;
        }
        auto bsonObj = elem.Obj();
        std::string databaseName = bsonObj.getStringField("name");
        return (databaseName == "admin");
    });
    if (adminIter != dbsArray.end()) {
        std::iter_swap(adminIter, dbsArray.begin());
    }
}
/* ****************************************************************************
*
* attributeType -
*
*/
static std::string attributeType
(
  const std::string&                    tenant,
  const std::vector<std::string>&       servicePathV,
  const std::string                     entityType,
  const std::string                     attrName
)
{
  std::string  idType         = std::string("_id.")    + ENT_ENTITY_TYPE;
  std::string  idServicePath  = std::string("_id.")    + ENT_SERVICE_PATH;
  std::string  attributeName  = std::string(ENT_ATTRS) + "." + attrName;

  BSONObj query = BSON(idType        << entityType <<
                       idServicePath << fillQueryServicePath(servicePathV) <<
                       attributeName << BSON("$exists" << true));

  std::auto_ptr<DBClientCursor> cursor;
  std::string                   err;

  if (!collectionQuery(getEntitiesCollectionName(tenant), query, &cursor, &err))
  {
    return "";
  }

  while (cursor->more())
  {
    BSONObj r;
    try
    {
      r = cursor->nextSafe();
    }
    catch (const AssertionException &e)
    {
      // $err raised
      LM_E(("Runtime Error (assertion exception in nextSafe(): %s", e.what()));
      continue;
    }

    LM_T(LmtMongo, ("retrieved document: '%s'", r.toString().c_str()));

    /* It could happen that different entities within the same entity type may have attributes with the same name
     * but different types. In that case, one type (at random) is returned. A list could be returned but the
     * NGSIv2 operations only allow to set one type */
    BSONObj attrs = getField(r, ENT_ATTRS).embeddedObject();
    BSONObj attr = getField(attrs, attrName).embeddedObject();
    return getStringField(attr, ENT_ATTRS_TYPE);
  }

  return "";
}
void Java_com_googlecode_eyesfree_textdetect_HydrogenTextDetector_nativeSetParameters(
    JNIEnv *env,
    jclass clazz,
    jlong nativePtr,
    jobject params) {
  if (DEBUG_MODE) LOGV(__FUNCTION__);

  HydrogenTextDetector *ptr = (HydrogenTextDetector *) nativePtr;
  HydrogenTextDetector::TextDetectorParameters *myParams = ptr->GetMutableParameters();

  jclass paramClass = env->GetObjectClass(params);

  getStringField(env, paramClass, params, "out_dir", myParams->out_dir);

  myParams->debug = getBoolField(env, paramClass, params, "debug");
  myParams->edge_tile_x = getIntField(env, paramClass, params, "edge_tile_x");
  myParams->edge_tile_y = getIntField(env, paramClass, params, "edge_tile_y");
  myParams->edge_thresh = getIntField(env, paramClass, params, "edge_thresh");
  myParams->edge_avg_thresh = getIntField(env, paramClass, params, "edge_avg_thresh");

  myParams->skew_enabled = getBoolField(env, paramClass, params, "skew_enabled");
  myParams->skew_min_angle = getFloatField(env, paramClass, params, "skew_min_angle");
  myParams->skew_sweep_range = getFloatField(env, paramClass, params, "skew_sweep_range");
  myParams->skew_sweep_delta = getFloatField(env, paramClass, params, "skew_sweep_delta");
  myParams->skew_sweep_reduction = getIntField(env, paramClass, params, "skew_sweep_reduction");
  myParams->skew_search_reduction = getIntField(env, paramClass, params, "skew_search_reduction");
  myParams->skew_search_min_delta = getFloatField(env, paramClass, params, "skew_search_min_delta");

  myParams->single_min_aspect = getFloatField(env, paramClass, params, "single_min_aspect");
  myParams->single_max_aspect = getFloatField(env, paramClass, params, "single_max_aspect");
  myParams->single_min_area = getIntField(env, paramClass, params, "single_min_area");
  myParams->single_min_density = getFloatField(env, paramClass, params, "single_min_density");

  myParams->pair_h_ratio = getFloatField(env, paramClass, params, "pair_h_ratio");
  myParams->pair_d_ratio = getFloatField(env, paramClass, params, "pair_d_ratio");
  myParams->pair_h_dist_ratio = getFloatField(env, paramClass, params, "pair_h_dist_ratio");
  myParams->pair_v_dist_ratio = getFloatField(env, paramClass, params, "pair_v_dist_ratio");
  myParams->pair_h_shared = getFloatField(env, paramClass, params, "pair_h_shared");

  myParams->cluster_width_spacing = getIntField(env, paramClass, params, "cluster_width_spacing");
  myParams->cluster_shared_edge = getFloatField(env, paramClass, params, "cluster_shared_edge");
  myParams->cluster_h_ratio = getFloatField(env, paramClass, params, "cluster_h_ratio");

  myParams->cluster_min_blobs = getIntField(env, paramClass, params, "cluster_min_blobs");
  myParams->cluster_min_aspect = getFloatField(env, paramClass, params, "cluster_min_aspect");
  myParams->cluster_min_fdr = getFloatField(env, paramClass, params, "cluster_min_fdr");
  myParams->cluster_min_edge = getIntField(env, paramClass, params, "cluster_min_edge");
  myParams->cluster_min_edge_avg = getIntField(env, paramClass, params, "cluster_min_edge_avg");
}
void NetworkInterfaceIntegrationFixture::assertWriteError(StringData db,
                                                          const BSONObj& cmd,
                                                          ErrorCodes::Error reason,
                                                          Milliseconds timeoutMillis) {
    RemoteCommandRequest request{
        fixture().getServers()[0], db.toString(), cmd, BSONObj(), nullptr, timeoutMillis};
    auto res = runCommandSync(request);
    ASSERT_OK(res.status);
    ASSERT_OK(getStatusFromCommandResult(res.data));
    ASSERT(res.data["writeErrors"]);
    auto firstWriteError = res.data["writeErrors"].embeddedObject().firstElement().embeddedObject();
    Status writeErrorStatus(ErrorCodes::Error(firstWriteError.getIntField("code")),
                            firstWriteError.getStringField("errmsg"));
    ASSERT_EQ(reason, writeErrorStatus);
}
COleDateTime CppSQLite3Query::getTimeField(int nField, time_t tNullValue /*= 0*/)
{
    CString str = getStringField(nField);
	if (str.IsEmpty())
	{
		if (0 == tNullValue)
            return WizGetCurrentTime();
		else
            return COleDateTime(tNullValue);
	}
	else
	{
		return WizStringToDateTime(str);
	}
}
Exemple #8
0
void ParamItem::update() {
	double min = getDoubleField(1);
	double current = getDoubleField(2);
	double max = getDoubleField(3);
	Q_ASSERT(min <= max);
	Q_ASSERT(min <= current && current <= max);

	ui->paramName->setText(getStringField(0));

	ui->MinLabel->setText(QString::number(min));

	ui->CurrentValueEdit->setText(QString::number(current));

	ui->MaxLabel->setText(QString::number(max));

	int sliderCurrent = qRound64((current - min) / (max - min) * maxValue);
	Q_ASSERT(0 <= sliderCurrent && sliderCurrent <= maxValue);
	ui->paramSlider->setValue(sliderCurrent);
}
int forOnAllTrade(lua_State *L)
{
    if (!lua_istable(L, -1))
        luaL_error(L, "OnAllTrade argument is not a table");

    TradeData data;

    data.code = getStringField(L, "sec_code");
    data.price = getNumberField(L, "price");
    data.amount = (unsigned long) getNumberField(L, "qty");
    data.trade_id = (unsigned long) getNumberField(L, "trade_num");

    lua_getfield(L, -1, "datetime");
    if (!lua_istable(L, -1))
    {
        luaL_error(L, "datetime is not a table");
    }

    int year = (int) getNumberField(L, "year");
    int month = (int) getNumberField(L, "month");
    int day = (int) getNumberField(L, "day");
    int hour = (int) getNumberField(L, "hour");
    int min = (int) getNumberField(L, "min");
    int sec = (int) getNumberField(L, "sec");
    int ms = (int) getNumberField(L, "ms");

    //2015-11-06 18:44:59.473
    if ( sprintf(data.dat_time, "%d-%.2d-%.2d %.2d:%.2d:%.2d:%.3d", year, month, day, hour, min, sec, ms) > dat_time_buf)
        luaL_error(L, "dat_time_buf overflow");

    lua_pop(L, 1);

    //FORTS csv format for features: "code;contract;price;amount;dat_time;trade_id;Nosystem"
    printf("%s;;%f;%Iu;%s;%Iu;0\n", data.code, data.price, data.amount, data.dat_time, data.trade_id);
    fflush(stdout);
    return 0;
}
const char* SqlStatement::ResultRow::getStringField(const char* szField, const char* szNullValue/*=""*/) const {
	return getStringField(fieldIndex(szField), szNullValue);
}
Exemple #11
0
void MyFmsNotifyEvent::notify() const
{	
	switch(m_pAev->getType())
	{
		case IFmsAuthEvent::E_PLAY:
		{
			char* pAppName = getStringField(m_pAev, IFmsAuthEvent::F_APP_NAME);
			char* pAppInst = getStringField(m_pAev, IFmsAuthEvent::F_APP_INST);
			char* pAppUri = getStringField(m_pAev, IFmsAuthEvent::F_APP_URI);
			
			///new prtmp fields
			I8 sValue;
			if (getI8Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP, sValue))
			{
				bool isProtected = sValue != 0;
			}
			char* pCommonKeyPath = getStringField(m_pAev, IFmsAuthEvent::F_APP_PRTMP_COMMON_KEY_FILE);
			U32 u32Value;
			if (getU32Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP_VIDEO_ENC_LEVEL, u32Value))
			{
				U32 videoEncyption = u32Value;
			}
			I32 iValue;
			if (getI32Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP_UPDATE_INTERVAL, iValue))
			{
				I32 updateInterval = iValue;
			}
			if (getI8Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP_SWF_VERIFICATION, sValue))
			{
				bool isPrtmpSwf = sValue != 0;
			}
            char* pWhiteListPath = getStringField(m_pAev, IFmsAuthEvent::F_APP_PRTMP_SWF_WHITELIST_FOLDER);
			////////

			char* pClIp = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_IP);
			char* pClUri = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_URI);
			char* pClNewUri = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_REDIRECT_URI);
			char* pClVhost = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_VHOST);
			char* pClRef = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_REFERRER);
			char* pClPurl = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_PAGE_URL);
			char* pClAgent = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_USER_AGENT);
			char* pClRAccess = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_READ_ACCESS);
			char* pClWAccess = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_WRITE_ACCESS);
			char* pClAudioAccess = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_AUDIO_SAMPLE_ACCESS);
			char* pClVideoAccess = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_VIDEO_SAMPLE_ACCESS);
			char* pClProto = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_PROTO);
			char* pClUstem = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_URI_STEM);
			
			char* pStreamName = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_NAME);
			char* pStreamType = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_TYPE);
			char* pStreamQuery = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_QUERY);
			char* pStreamPath = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_PATH);
			
			if (getI32Field(m_pAev, IFmsAuthEvent::F_CLIENT_AUDIO_CODECS, iValue))
			{
				bool bADPCM = isADPCMSupported(iValue);
			}
			if (getI32Field(m_pAev, IFmsAuthEvent::F_CLIENT_VIDEO_CODECS, iValue))
			{
				bool bVP6 = isVP6Supported(iValue);
			}			
			if (getI32Field(m_pAev, IFmsAuthEvent::F_CLIENT_TYPE, iValue))
			{	
				bool bService = isService(iValue);
			}
			if (getI32Field(m_pAev, IFmsAuthEvent::F_STREAM_ID, iValue))
			{	
				I32 iStreamId = iValue;
			}
						
			float fValue;
			if (getFloatField(m_pAev, IFmsAuthEvent::F_STREAM_LENGTH, fValue))
			{
				float fLength = fValue; // in seconds
			}
			if (getFloatField(m_pAev, IFmsAuthEvent::F_STREAM_POSITION, fValue))
			{
				float iPosition = fValue; // in seconds
			}

			I64 lValue;
			if (getI64Field(m_pAev, IFmsAuthEvent::F_CLIENT_ID, lValue))
			{
				I64 iClientId = lValue;		
			}
						
			
			if (getI8Field(m_pAev, IFmsAuthEvent::F_CLIENT_SECURE, sValue))
			{
				bool bSecure = sValue != 0;
			}
			if (getI8Field(m_pAev, IFmsAuthEvent::F_CLIENT_AMF_ENCODING, sValue))
			{
				bool bAMF3 = isAMF3(sValue);
			}
			if (getI8Field(m_pAev, IFmsAuthEvent::F_CLIENT_READ_ACCESS_LOCK, sValue))
			{			
				bool bRead = sValue != 0;
			}
			if (getI8Field(m_pAev, IFmsAuthEvent::F_CLIENT_WRITE_ACCESS_LOCK, sValue))
			{
				bool bWrite = sValue != 0;
			}
			if (getI8Field(m_pAev, IFmsAuthEvent::F_CLIENT_AUDIO_SAMPLE_ACCESS_LOCK, sValue))
			{
				bool bAudioRead = sValue != 0;
			}
			if (getI8Field(m_pAev, IFmsAuthEvent::F_CLIENT_VIDEO_SAMPLE_ACCESS_LOCK, sValue))
			{
				bool bVideoRead = sValue != 0;
			}
			if (getI8Field(m_pAev, IFmsAuthEvent::F_STREAM_RESET, sValue))
			{
				bool bReset = sValue != 0;
			}
			if (getI8Field(m_pAev, IFmsAuthEvent::F_STREAM_IGNORE, sValue))
			{
				bool bIgnore = sValue != 0;
			}
		}			
		break;
		
		case IFmsAuthEvent::E_SEEK:
		{
			float fValue;
			if (getFloatField(m_pAev, IFmsAuthEvent::F_STREAM_SEEK_POSITION, fValue))
			{
				float fSeekTime = fValue;
			}

			// Disconnect Action example: disconnect the client that was 
			// specified by the E_SEEK notify event 
			FmsVariant field;
			if (m_pAev->getField(IFmsAuthEvent::F_CLIENT_ID, field) == IFmsAuthEvent::S_SUCCESS)
			{
				IFmsDisconnectAction* pAction = 
					const_cast<IFmsAuthEvent*>(m_pAev)->
						addDisconnectAction("Seek is not allowed. Blocked by adaptor");
				pAction->setClientId(field);
			}
		}
		break;

		case IFmsAuthEvent::E_CODEC_CHANGE:
		{
			char* pAppName = getStringField(m_pAev, IFmsAuthEvent::F_APP_NAME);
			char* pAppInst = getStringField(m_pAev, IFmsAuthEvent::F_APP_INST);
			char* pAppUri = getStringField(m_pAev, IFmsAuthEvent::F_APP_URI);
			
			char* pClIp = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_IP);
			char* pClUri = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_URI);
			char* pClNewUri = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_REDIRECT_URI);
			char* pClVhost = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_VHOST);
			char* pClRef = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_REFERRER);
			char* pClPurl = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_PAGE_URL);
			char* pClAgent = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_USER_AGENT);
			char* pClRAccess = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_READ_ACCESS);
			char* pClWAccess = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_WRITE_ACCESS);
			char* pClAudioAccess = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_AUDIO_SAMPLE_ACCESS);
			char* pClVideoAccess = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_VIDEO_SAMPLE_ACCESS);
			char* pClProto = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_PROTO);
			char* pClUstem = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_URI_STEM);
			
			char* pStreamName = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_NAME);
			char* pStreamType = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_TYPE);
			char* pStreamQuery = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_QUERY);
			char* pStreamPath = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_PATH);

			U16 fType;
			if (getU16Field(m_pAev, IFmsAuthEvent::F_STREAM_CODEC_TYPE, fType))
			{
				U16 streamCodecType = fType;
				if (streamCodecType == kVIDEO_CODEC)
				{
					U16 fValue;
					if (getU16Field(m_pAev, IFmsAuthEvent::F_STREAM_CODEC, fValue))
					{				
						U16 streamCodecValue = fValue;
						if (streamCodecValue == VIDEO_CODEC_SORENSON)
						{
							// Disconnect Action example: Disallow clients trying 
							// to publish content with the sorenson video codec.
							FmsVariant field;
							if (m_pAev->getField(IFmsAuthEvent::F_CLIENT_ID, field) == IFmsAuthEvent::S_SUCCESS)
							{
								IFmsDisconnectAction* pAction = 
									const_cast<IFmsAuthEvent*>(m_pAev)->
									addDisconnectAction("Sorenson is not allowed. Blocked by adaptor");
								pAction->setClientId(field);
							}
						}
					}		
				}
			}				
		}
		break;
		case IFmsAuthEvent::E_RECORD_STOP:
		{
			char* pAppName = getStringField(m_pAev, IFmsAuthEvent::F_APP_NAME);
			char* pAppInst = getStringField(m_pAev, IFmsAuthEvent::F_APP_INST);
			char* pAppUri = getStringField(m_pAev, IFmsAuthEvent::F_APP_URI);
			
			char* pClIp = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_IP);
			char* pClUri = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_URI);
			char* pClNewUri = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_REDIRECT_URI);
			char* pClVhost = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_VHOST);
			char* pClRef = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_REFERRER);
			char* pClPurl = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_PAGE_URL);
			char* pClAgent = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_USER_AGENT);
			char* pClRAccess = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_READ_ACCESS);
			char* pClWAccess = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_WRITE_ACCESS);
			char* pClAudioAccess = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_AUDIO_SAMPLE_ACCESS);
			char* pClVideoAccess = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_VIDEO_SAMPLE_ACCESS);
			char* pClProto = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_PROTO);
			char* pClUstem = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_URI_STEM);
			
			char* pStreamName = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_NAME);
			char* pStreamType = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_TYPE);
			char* pStreamQuery = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_QUERY);
			char* pStreamPath = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_PATH);
			
			float fValue;	
			if (getFloatField(m_pAev, IFmsAuthEvent::F_STREAM_RECORD_MAXSIZE, fValue))
			{
				float recMaxSize = fValue; // in kilobytes
			}			
			if (getFloatField(m_pAev, IFmsAuthEvent::F_STREAM_RECORD_MAXDURATION, fValue))
			{
				float recMaxDuration = fValue;	// in seconds
			}	
		}
		break;
		case IFmsAuthEvent::E_SWF_VERIFY_COMPLETE:
		{
			char* pClIp = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_IP);

			I8 version;	// version of SWF verification 
			getI8Field(m_pAev, IFmsAuthEvent::F_CLIENT_SWFV_VERSION, version);

			I64 depth; // depth in the SWF file hashed
			getI64Field(m_pAev, IFmsAuthEvent::F_CLIENT_SWFV_DEPTH, depth);

			I32 ttl; // time to live of the SWF hash provided
			getI32Field(m_pAev, IFmsAuthEvent::F_CLIENT_SWFV_TTL, ttl);

			// digest provided to match against
			U8* buffer = getBufferField(m_pAev, IFmsAuthEvent::F_CLIENT_SWFV_DIGEST);

			// result of the attempted match-- see FmsAuthEvents.h enum
			// eSWFMatch for the meaning of this field
			I32 match;	
			getI32Field(m_pAev, IFmsAuthEvent::F_CLIENT_SWFV_RESULT, match);

			std::stringstream stream;
			stream << "swf verification for client: " 
					<< std::string(pClIp) 
					<< " is complete, the result is: " << match;
			m_pFmsAuthServerContext->log(stream.str().c_str(), IFmsServerContext::kInformation, false);
		}
		break;

		case IFmsAuthEvent::E_APPSTART:
		case IFmsAuthEvent::E_APPSTOP:
		case IFmsAuthEvent::E_CONNECT:
		case IFmsAuthEvent::E_DISCONNECT:
		case IFmsAuthEvent::E_FILENAME_TRANSFORM:
		case IFmsAuthEvent::E_STOP:
		case IFmsAuthEvent::E_PAUSE:
		case IFmsAuthEvent::E_PUBLISH:
		case IFmsAuthEvent::E_UNPUBLISH:
		case IFmsAuthEvent::E_LOADSEGMENT:
		case IFmsAuthEvent::E_ACTION:
		case IFmsAuthEvent::E_RECORD:
		case IFmsAuthEvent::E_CLIENT_PAUSE:
		case IFmsAuthEvent::E_SWF_VERIFY:
		case IFmsAuthEvent::E_CLIENT_SEEK:
		case IFmsAuthEvent::E_START_TRANSMIT:
		case IFmsAuthEvent::E_STOP_TRANSMIT:
		case IFmsAuthEvent::E_MAXEVENT:
		break;

	}	
	char buf[1024];
	sprintf(buf, "Received notification type=%d id=%p\n", m_pAev->getType(), m_pAev);

	// log to the configured FMS log directory. If the third parameter is true,
	// also send the log to the system event log.
	m_pFmsAuthServerContext->log(buf, IFmsServerContext::kInformation, false); 
	m_pFmsAuthServerContext->onNotify(m_pAev);
}
Exemple #12
0
void MyFmsAuthorizeEvent::authorize()
{
	bool bAuthorized = true;  // default authorization state
	
	switch(m_pAev->getType())
	{
		case IFmsAuthEvent::E_APPSTART:
		{
			// only E_APPSTART allows changes to the following fields: 
			// F_APP_PRTMP
			// F_APP_PRTMP_COMMON_KEY_FILE
			// F_APP_PRTMP_VIDEO_ENC_LEVEL
			// F_APP_PRTMP_UPDATE_INTERVAL
			// F_APP_PRTMP_SWF_VERIFICATION
			// F_APP_PRTMP_SWF_WHITELIST_FOLDER
			bool bSet;
			I8 sValue;
			if (getI8Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP, sValue))
			{
				bSet = setI8Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP, sValue);
			}

			char* pCommonKeyPath = getStringField(m_pAev, IFmsAuthEvent::F_APP_PRTMP_COMMON_KEY_FILE); 
			if (pCommonKeyPath)
			{				
				bSet = setStringField(m_pAev, IFmsAuthEvent::F_APP_PRTMP_COMMON_KEY_FILE, 
					pCommonKeyPath);					
			}
			
			U32 uValue;
			if (getU32Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP_VIDEO_ENC_LEVEL, uValue))
			{
				bSet = setU32Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP_VIDEO_ENC_LEVEL, uValue);
			}

			I32 iValue;
			if (getI32Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP_UPDATE_INTERVAL, iValue))
			{
				bSet = setI32Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP_UPDATE_INTERVAL, iValue);
			}

			if (getI8Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP_SWF_VERIFICATION, sValue))
			{
				bSet = setI8Field(m_pAev, IFmsAuthEvent::F_APP_PRTMP_SWF_VERIFICATION, sValue);
			}

			char* pWhiteListPath = getStringField(m_pAev, IFmsAuthEvent::F_APP_PRTMP_SWF_WHITELIST_FOLDER); 
			if (pWhiteListPath)
			{				
				bSet = setStringField(m_pAev, IFmsAuthEvent::F_APP_PRTMP_SWF_WHITELIST_FOLDER, 
					pWhiteListPath);					
			}

			bAuthorized = true;	
			
		}
		break;	
		case IFmsAuthEvent::E_CONNECT:
		{
			// only E_CONNECT allows changes to the following fields: 
			// F_CLIENT_AUDIO_SAMPLE_ACCESS
			// F_CLIENT_AUDIO_SAMPLE_ACCESS_LOCK
			// F_CLIENT_READ_ACCESS
			// F_CLIENT_READ_ACCESS_LOCK
			// F_CLIENT_VIDEO_SAMPLE_ACCESS
			// F_CLIENT_VIDEO_SAMPLE_ACCESS_LOCK
			// F_CLIENT_WRITE_ACCESS_LOCK
			// F_CLIENT_WRITE_ACCESS
			I8 iValue;
			if (getI8Field(m_pAev, IFmsAuthEvent::F_CLIENT_WRITE_ACCESS, iValue))
			{
				setI8Field(m_pAev, IFmsAuthEvent::F_CLIENT_WRITE_ACCESS, iValue);
			}

			// redirect connection example
			char* pUri = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_URI); 
			if (pUri && !strcmp(pUri, "rtmp://localhost/streamtest"))
			{				
				setStringField(m_pAev, IFmsAuthEvent::F_CLIENT_REDIRECT_URI, 
					"rtmp://localhost:1935/streamtest");
				bAuthorized = false;	
			}

			// set DiffServ fields based on a client IP 
			// char* pIp = getStringField(m_pAev, IFmsAuthEvent::F_CLIENT_IP); 
			// if (pIp && !strcmp(pIp, "192.168.1.1"))
			{				
				// set the DSCP bits and mask
				U8 m_diffServBits = 170;
				U8 m_diffServMask = 252;
				setU8Field(m_pAev, IFmsAuthEvent::F_CLIENT_DIFFSERV_BITS, m_diffServBits);
				setU8Field(m_pAev, IFmsAuthEvent::F_CLIENT_DIFFSERV_MASK, m_diffServMask);

				bAuthorized = true;	
			}
		}
		break;	
		case IFmsAuthEvent::E_PLAY:
		{			
			char* pStreamName = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_NAME); 
			if (pStreamName)
			{
				setStringField(m_pAev, IFmsAuthEvent::F_STREAM_NAME, pStreamName);
			}			
			char* pStreamType = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_TYPE);
			if (pStreamType)
			{
				setStringField(m_pAev, IFmsAuthEvent::F_STREAM_TYPE, pStreamType);
			}			
			char* pStreamQuery = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_QUERY);
			if (pStreamQuery)
			{
				setStringField(m_pAev, IFmsAuthEvent::F_STREAM_QUERY, pStreamQuery);
			}			
			m_pFmsAuthServerContext->log(pStreamName, IFmsServerContext::kInformation, false);
			m_pFmsAuthServerContext->log(pStreamType, IFmsServerContext::kInformation, false);
			m_pFmsAuthServerContext->log(pStreamQuery, IFmsServerContext::kInformation, false);

			I8 iValue;
			if (getI8Field(m_pAev, IFmsAuthEvent::F_STREAM_RESET, iValue))
			{
				// If iValue is 1 (true) the playlist will be reset and the 
				// stream will be the only stream in the playlist; otherwise 
				// 0 (false) means the stream will be added to the existing
				// playlist.
				setI8Field(m_pAev, IFmsAuthEvent::F_STREAM_RESET, iValue);	
			}
			if (getI8Field(m_pAev, IFmsAuthEvent::F_STREAM_IGNORE, iValue))
			{
				// If iValue is 1 (true) the stream timestamps will be ignored;
				// otherwise 0 (false) means the timestamps will be handled.
				setI8Field(m_pAev, IFmsAuthEvent::F_STREAM_IGNORE, iValue);	
			}
			
			char* pStreamTransition = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_TRANSITION); 
			if (pStreamTransition && strlen(pStreamTransition))
			{				
				// MBR transition example
				if (!strcmp(pStreamTransition, "switch") ||
					!strcmp(pStreamTransition, "swap"))
				{					
					// get the old stream's properties 
					char* pOldStreamName = getStringField(m_pAev, IFmsAuthEvent::F_OLD_STREAM_NAME);
					char* pOldStreamType = getStringField(m_pAev, IFmsAuthEvent::F_OLD_STREAM_TYPE);
					char* pOldStreamQuery = getStringField(m_pAev, IFmsAuthEvent::F_OLD_STREAM_QUERY);

					// if pOldStream is empty (optional for switch) current stream is in play
					// do we really want stream transition? 	
					{
						// no we do not allow transition
						// bAuthorized = false;
						// now transition will be turned off and old stream continue playing
						// break;					
					}
					// doing nothing will execute transition mode as is
					// or you could modify transition by changing transition properties

					// set it to 1 to indicate they will be hooking up the stream, 
					// but that it does not currently exist
					setI32Field(m_pAev, IFmsAuthEvent::F_STREAM_LIVE_PUBLISH_PENDING, 1);	
				}	

				// get the offset value if transition is set to offset mode for reconnect
				if (!strcmp(pStreamTransition, "resume"))
				{
					float fValue;
					if (getFloatField(m_pAev, IFmsAuthEvent::F_STREAM_OFFSET, fValue))
					{
						float offset = fValue; //offset value in seconds
					}			
				}
			}
			else
			{
				// This is a regular play waiting for approval, which may be converted
				// into a play2 command by changing transition properties
			}	
		}
		break;
		case IFmsAuthEvent::E_PUBLISH:
		{	
			char* pStreamName = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_NAME); 
			if (pStreamName)
			{
				setStringField(m_pAev, IFmsAuthEvent::F_STREAM_NAME, pStreamName);
			}	
			char* pStreamType = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_TYPE);
			if (pStreamType)
			{
				setStringField(m_pAev, IFmsAuthEvent::F_STREAM_TYPE, pStreamType);
			}
			I32 iValue;
			if (getI32Field(m_pAev, IFmsAuthEvent::F_STREAM_PUBLISH_TYPE, iValue))
			{
				// publish types:
				// 0 : record
				// 1 : append
				// 2 : appendWithGap
				// -1 : live
				setI32Field(m_pAev, IFmsAuthEvent::F_STREAM_PUBLISH_TYPE, iValue);	
			}
		} 		
		break;
		case IFmsAuthEvent::E_FILENAME_TRANSFORM:
			{
				I64 iValue;
				if (getI64Field(m_pAev, IFmsAuthEvent::F_CLIENT_ID, iValue))
				{
					// some fields are not eligible to be modified. The return
					// value will be false when trying to modify the F_CLIENT_ID.
					bool bSet = setI64Field(m_pAev, IFmsAuthEvent::F_CLIENT_ID, iValue); 
				}
				char* pStreamName = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_NAME); 
				if (pStreamName)
				{
					// some fields are not eligible to be modified. The return
					// value will be false when trying to modify the F_STREAM_NAME.
					bool bSet = setStringField(m_pAev, IFmsAuthEvent::F_STREAM_NAME, pStreamName); 
				}
				char* pStreamPath = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_PATH); 
				if (pStreamPath)
				{
					setStringField(m_pAev, IFmsAuthEvent::F_STREAM_PATH, pStreamPath);
				}				
				char* pStreamType = getStringField(m_pAev, IFmsAuthEvent::F_STREAM_TYPE);
				if (pStreamType)
				{
					setStringField(m_pAev, IFmsAuthEvent::F_STREAM_TYPE, pStreamType);		
				}						
			}
		break;
		case IFmsAuthEvent::E_PAUSE:
		{
			bAuthorized = false; // block all E_PAUSE events.
						
			float fValue;
			if (getFloatField(m_pAev, IFmsAuthEvent::F_STREAM_PAUSE_TIME, fValue))
			{
				float fPauseTime = fValue;	// in seconds
			}		
			
			I8 iValue;
			if (getI8Field(m_pAev, IFmsAuthEvent::F_STREAM_PAUSE, iValue))
			{
				// 1 (true) means PAUSE
				// 0 (false) means UNPAUSE
				bool boolPause = iValue != 0;	
			}			
			if (getI8Field(m_pAev, IFmsAuthEvent::F_STREAM_PAUSE_TOGGLE, iValue))
			{
				// 1 (true) means PAUSE_TOGGLE
				// 0 (false) means no PAUSE_TOGGLE was set
				bool boolPauseToggle = iValue != 0;	
			}	
		
			FmsVariant field;
			
			// Notify Action example: An IFmsNofifyAction is created to notify
			// server side action script (SSAS) of the E_PAUSE event by calling
			// the function name "method" in the script.  In this example two
			// variables will be passed to "method" by calling addParam(field)
			// on the action.
			if (m_pAev->getField(IFmsAuthEvent::F_CLIENT_ID, field) == IFmsAuthEvent::S_SUCCESS)
			{
				I64 clientId = field.i64;
				IFmsNotifyAction* pAction = m_pAev->addNotifyAction("Notified by adaptor");
				pAction->setClientId(field);
				const char mtd[] = "method";
				field.setString(reinterpret_cast<I8*>(const_cast<char*>(mtd)));
				pAction->setMethodName(field);

				// create and insert a U16 "12345" as the first parameter 
				field.setU16(12345);
				pAction->addParam(field);

				// create and insert clientId as a double as the second parameter 
				field.setDouble((double)clientId);
				pAction->addParam(field);
				
				// Note: SSAS does not work with I64 or Buffer variants
				// field.setI64(clientId); 
				// pAction->addParam(field); // incorrect
			}
		}
		break;
		case IFmsAuthEvent::E_SEEK:
		{
			bAuthorized = false; // block all E_SEEK events
			
			float fValue;
			if (getFloatField(m_pAev, IFmsAuthEvent::F_STREAM_SEEK_POSITION, fValue))
			{
				// Modification of the seek position example:
				// fValue + 3; will add 3 seconds to the initial seek posistion
				float fSeekTime = fValue; // value in seconds
				setFloatField(m_pAev, IFmsAuthEvent::F_STREAM_SEEK_POSITION, fSeekTime);
			}			
		}
		break;
		case IFmsAuthEvent::E_LOADSEGMENT:
		{
			// bAuthorized = false;	// block all E_LOADSEGMENT events
			// E_LOADSEGMENT is a read only event that substitutes E_PLAY on 
			// FMS Origin servers for recorded streams.
			
			I64 iValue;	
			if (getI64Field(m_pAev, IFmsAuthEvent::F_SEGMENT_START, iValue))
			{
				I64 iStart = iValue; // in bytes
			}			
			if (getI64Field(m_pAev, IFmsAuthEvent::F_SEGMENT_END, iValue))
			{
				I64 iEnd = iValue;	// in bytes
			}			
		}
		break;
		case IFmsAuthEvent::E_RECORD:
		{
			// bAuthorized = false;	// block all E_RECORD events
			float fValue;	
			if (getFloatField(m_pAev, IFmsAuthEvent::F_STREAM_RECORD_MAXSIZE, fValue))
			{
				float recMaxSize = fValue; // in kilobytes
				setFloatField(m_pAev, IFmsAuthEvent::F_STREAM_RECORD_MAXSIZE, recMaxSize);
			}			
			if (getFloatField(m_pAev, IFmsAuthEvent::F_STREAM_RECORD_MAXDURATION, fValue))
			{
				float recMaxDuration = fValue;	// in seconds
				setFloatField(m_pAev, IFmsAuthEvent::F_STREAM_RECORD_MAXDURATION, recMaxDuration);
			}	
		}
		break;
		case IFmsAuthEvent::E_SWF_VERIFY:
		{
			// SWF Verification example:
			// kAuthorizeSwfVerification is assigned false by default.  The
			// target SWF file must be updated for this to work.
			if(kAuthorizeSwfVerification) 
			{
				I8 swfvVersion = 0;
				if(getI8Field(m_pAev, IFmsAuthEvent::F_CLIENT_SWFV_VERSION, swfvVersion))
				{
					std::stringstream stream;
					stream << "Swf verification version is " << static_cast<int>(swfvVersion);
					m_pFmsAuthServerContext->log(stream.str().c_str(), IFmsServerContext::kInformation, false);
				}
				I64 swfvDepth;
				if(getI64Field(m_pAev, IFmsAuthEvent::F_CLIENT_SWFV_DEPTH, swfvDepth))
				{				
					I32 swfvTTL;
					if(getI32Field(m_pAev, IFmsAuthEvent::F_CLIENT_SWFV_TTL, swfvTTL))
					{
						swfvTTL /= 2;
						setI32Field(m_pAev, IFmsAuthEvent::F_CLIENT_SWFV_TTL, swfvTTL);
					}

					U8 digest[kSHA256DigestLen];

					// Target a real SWF file instead of sample.swf 
					hashSwfFileAtDepth("C:\\sample.swf", swfvDepth, digest);

					FmsVariant field;
					field.setBuffer(digest, kSHA256DigestLen);	
					m_pAev->setField(IFmsAuthEvent::F_CLIENT_SWFV_DIGEST, field);
				}
			}			
		}
		break;
		
		case IFmsAuthEvent::E_APPSTOP:
		case IFmsAuthEvent::E_DISCONNECT:
		case IFmsAuthEvent::E_STOP:
		case IFmsAuthEvent::E_UNPUBLISH:
		case IFmsAuthEvent::E_ACTION:
		case IFmsAuthEvent::E_CODEC_CHANGE:
		case IFmsAuthEvent::E_RECORD_STOP:
		case IFmsAuthEvent::E_CLIENT_PAUSE:
		case IFmsAuthEvent::E_SWF_VERIFY_COMPLETE:
		case IFmsAuthEvent::E_CLIENT_SEEK:
		case IFmsAuthEvent::E_START_TRANSMIT:
		case IFmsAuthEvent::E_STOP_TRANSMIT:
		case IFmsAuthEvent::E_MAXEVENT:
		break;
	}
	
	IFmsAuthServerContext2::AuthFailureDesc* desc = NULL;
	
	if(!bAuthorized)
	{
		desc = new IFmsAuthServerContext2::AuthFailureDesc("Blocked by auth adaptor", 
			IFmsAuthServerContext2::kDefaultStatus, -1);
	}		
	char buf[1024];
	const char* const action = bAuthorized ? "approved" : "rejected";
	sprintf(buf, "Received dddd authorization type=%d id=%p %s\n", m_pAev->getType(), 
		m_pAev, action);

	char tlog[1024];
	sprintf(tlog,"bb\n");
	m_pFmsAuthServerContext->log(tlog, IFmsServerContext::kInformation, false) 
	
	// log to the configured FMS log directory. If the third parameter is true,
	// also send the log to the system event log.
	m_pFmsAuthServerContext->log(buf, IFmsServerContext::kInformation, false); 
	
	m_pFmsAuthServerContext->onAuthorize(m_pAev, bAuthorized, desc);
	delete desc;
}
/* ****************************************************************************
*
* mongoEntityTypes -
*/
HttpStatusCode mongoEntityTypes
(
  EntityTypeVectorResponse*                  responseP,
  const std::string&                    tenant,
  const std::vector<std::string>&       servicePathV,
  std::map<std::string, std::string>&   uriParams
)
{
  unsigned int   offset         = atoi(uriParams[URI_PARAM_PAGINATION_OFFSET].c_str());
  unsigned int   limit          = atoi(uriParams[URI_PARAM_PAGINATION_LIMIT].c_str());
  std::string    detailsString  = uriParams[URI_PARAM_PAGINATION_DETAILS];
  bool           details        = (strcasecmp("on", detailsString.c_str()) == 0)? true : false;  
  bool           reqSemTaken    = false;

  LM_T(LmtMongo, ("Query Entity Types"));
  LM_T(LmtPagination, ("Offset: %d, Limit: %d, Details: %s", offset, limit, (details == true)? "true" : "false"));

  reqSemTake(__FUNCTION__, "query types request", SemReadOp, &reqSemTaken);

  /* Compose query based on this aggregation command:  
   *
   * db.runCommand({aggregate: "entities",
   *                pipeline: [ {$match: { "_id.servicePath": /.../ } },
   *                            {$project: {_id: 1, "attrNames": 1} },
   *                            {$project: { "attrNames"
   *                                  {$cond: [ {$eq: [ "$attrNames", [ ] ] }, [null], "$attrNames"] }
   *                               }
   *                            },
   *                            {$unwind: "$attrNames"},
   *                            {$group: {_id: "$_id.type", attrs: {$addToSet: "$attrNames"}} },
   *                            {$sort: {_id: 1} }
   *                          ]
   *                })   
   *
   * The $cond part is hard... more information at http://stackoverflow.com/questions/27510143/empty-array-prevents-document-to-appear-in-query
   * As a consequence, some "null" values may appear in the resulting attrs vector, which are pruned by the result processing logic.
   *
   * FIXME P6: in the future, we can interpret the collapse parameter at this layer. If collapse=true so we don't need attributes, the
   * following command can be used:
   *
   * db.runCommand({aggregate: "entities", pipeline: [ {$group: {_id: "$_id.type"} }]})
   *
   *
   *
   */

  BSONObj result;

  //
  // Building the projection part of the query that includes types that have no attributes
  // See bug: https://github.com/telefonicaid/fiware-orion/issues/686
  //
  BSONArrayBuilder  emptyArrayBuilder;
  BSONArrayBuilder  nulledArrayBuilder;

  nulledArrayBuilder.appendNull();

  // We are using the $cond: [ .. ] and not the $cond: { .. } one, as the former is the only one valid in MongoDB 2.4
  BSONObj projection = BSON(
    "$project" << BSON(
      ENT_ATTRNAMES << BSON(
        "$cond" << BSON_ARRAY(
          BSON("$eq" << BSON_ARRAY(S_ATTRNAMES << emptyArrayBuilder.arr()) ) <<
          nulledArrayBuilder.arr() <<
          S_ATTRNAMES
        )
      )
    )
  );

  BSONObj cmd = BSON("aggregate" << COL_ENTITIES <<
                     "pipeline" << BSON_ARRAY(
                                              BSON("$match" << BSON(C_ID_SERVICEPATH << fillQueryServicePath(servicePathV))) <<
                                              BSON("$project" << BSON("_id" << 1 << ENT_ATTRNAMES << 1)) <<
                                              projection <<
                                              BSON("$unwind" << S_ATTRNAMES) <<
                                              BSON("$group" << BSON("_id" << CS_ID_ENTITY << "attrs" << BSON("$addToSet" << S_ATTRNAMES))) <<
                                              BSON("$sort" << BSON("_id" << 1))
                                             )
                     );

  std::string err;
  if (!runCollectionCommand(composeDatabaseName(tenant), cmd, &result, &err))
  {
    responseP->statusCode.fill(SccReceiverInternalError, err);
    reqSemGive(__FUNCTION__, "query types request", reqSemTaken);
    return SccOk;
  }

  // Processing result to build response
  LM_T(LmtMongo, ("aggregation result: %s", result.toString().c_str()));

  std::vector<BSONElement> resultsArray = getField(result, "result").Array();

  if (resultsArray.size() == 0)
  {
    responseP->statusCode.fill(SccContextElementNotFound);
    reqSemGive(__FUNCTION__, "query types request", reqSemTaken);

    return SccOk;
  }

  /* Another strategy to implement pagination is to use the $skip and $limit operators in the
   * aggregation framework. However, doing so, we don't know the total number of results, which can
   * be needed in the case of details=on (using that approach, we need to do two queries: one to get
   * the count and other to get the actual results with $skip and $limit, in the same "transaction" to
   * avoid incoherence between both if some entity type is created or deleted in the process).
   *
   * However, considering that the number of types will be small compared with the number of entities,
   * the current approach seems to be ok
   */
  for (unsigned int ix = offset; ix < MIN(resultsArray.size(), offset + limit); ++ix)
  {
    BSONObj                   resultItem  = resultsArray[ix].embeddedObject();
    EntityType*               entityType  = new EntityType(getStringField(resultItem, "_id"));
    std::vector<BSONElement>  attrsArray  = getField(resultItem, "attrs").Array();

    entityType->count = countEntities(tenant, servicePathV, entityType->type);

    if (!attrsArray[0].isNull())
    {
      for (unsigned int jx = 0; jx < attrsArray.size(); ++jx)
      {
        /* This is where NULL elements in the resulting attrs vector are pruned */
        if (attrsArray[jx].isNull())
        {
          continue;
        }

        /* Note that we need and extra query() to the database (inside attributeType() function) to get each attribute type.
         * This could be unefficient, specially if the number of attributes is large */
        std::string attrType = attributeType(tenant, servicePathV, entityType->type , attrsArray[jx].str());

        ContextAttribute* ca = new ContextAttribute(attrsArray[jx].str(), attrType, "");
        entityType->contextAttributeVector.push_back(ca);
      }
    }

    responseP->entityTypeVector.push_back(entityType);
  }

  char detailsMsg[256];
  if (responseP->entityTypeVector.size() > 0)
  {
    if (details)
    {
      snprintf(detailsMsg, sizeof(detailsMsg), "Count: %d", (int) resultsArray.size());
      responseP->statusCode.fill(SccOk, detailsMsg);
    }
    else
    {
      responseP->statusCode.fill(SccOk);
    }
  }
  else
  {
    if (details)
    {      
      snprintf(detailsMsg, sizeof(detailsMsg), "Number of types: %d. Offset is %d", (int) resultsArray.size(), offset);
      responseP->statusCode.fill(SccContextElementNotFound, detailsMsg);
    }
    else
    {
      responseP->statusCode.fill(SccContextElementNotFound);
    }
  }

  reqSemGive(__FUNCTION__, "query types request", reqSemTaken);

  return SccOk;

}
Exemple #14
0
LPCTSTR CppSQLite3Query::getStringField(LPCTSTR szField, LPCTSTR szNullValue/*=""*/)
{
	int nField = fieldIndex(szField);
	return getStringField(nField, szNullValue);
}
StatusWith<ShardType> ShardingCatalogManager::_validateHostAsShard(
    OperationContext* opCtx,
    std::shared_ptr<RemoteCommandTargeter> targeter,
    const std::string* shardProposedName,
    const ConnectionString& connectionString) {
    auto swCommandResponse = _runCommandForAddShard(
        opCtx, targeter.get(), NamespaceString::kAdminDb, BSON("isMaster" << 1));
    if (swCommandResponse.getStatus() == ErrorCodes::IncompatibleServerVersion) {
        return swCommandResponse.getStatus().withReason(
            str::stream() << "Cannot add " << connectionString.toString()
                          << " as a shard because its binary version is not compatible with "
                             "the cluster's featureCompatibilityVersion.");
    } else if (!swCommandResponse.isOK()) {
        return swCommandResponse.getStatus();
    }

    // Check for a command response error
    auto resIsMasterStatus = std::move(swCommandResponse.getValue().commandStatus);
    if (!resIsMasterStatus.isOK()) {
        return resIsMasterStatus.withContext(str::stream()
                                             << "Error running isMaster against "
                                             << targeter->connectionString().toString());
    }

    auto resIsMaster = std::move(swCommandResponse.getValue().response);

    // Fail if the node being added is a mongos.
    const std::string msg = resIsMaster.getStringField("msg");
    if (msg == "isdbgrid") {
        return {ErrorCodes::IllegalOperation, "cannot add a mongos as a shard"};
    }

    // Extract the maxWireVersion so we can verify that the node being added has a binary version
    // greater than or equal to the cluster's featureCompatibilityVersion. We expect an incompatible
    // binary node to be unable to communicate, returning an IncompatibleServerVersion error,
    // because of our internal wire version protocol. So we can safely invariant here that the node
    // is compatible.
    long long maxWireVersion;
    Status status = bsonExtractIntegerField(resIsMaster, "maxWireVersion", &maxWireVersion);
    if (!status.isOK()) {
        return status.withContext(str::stream() << "isMaster returned invalid 'maxWireVersion' "
                                                << "field when attempting to add "
                                                << connectionString.toString()
                                                << " as a shard");
    }
    if (serverGlobalParams.featureCompatibility.getVersion() >
        ServerGlobalParams::FeatureCompatibility::Version::kFullyDowngradedTo40) {
        // If the cluster's FCV is 4.2, or upgrading to / downgrading from, the node being added
        // must be a v4.2 binary.
        invariant(maxWireVersion == WireVersion::LATEST_WIRE_VERSION);
    } else {
        // If the cluster's FCV is 4.0, the node being added must be a v4.0 or v4.2 binary.
        invariant(serverGlobalParams.featureCompatibility.getVersion() ==
                  ServerGlobalParams::FeatureCompatibility::Version::kFullyDowngradedTo40);
        invariant(maxWireVersion >= WireVersion::LATEST_WIRE_VERSION - 1);
    }

    // Check whether there is a master. If there isn't, the replica set may not have been
    // initiated. If the connection is a standalone, it will return true for isMaster.
    bool isMaster;
    status = bsonExtractBooleanField(resIsMaster, "ismaster", &isMaster);
    if (!status.isOK()) {
        return status.withContext(str::stream() << "isMaster returned invalid 'ismaster' "
                                                << "field when attempting to add "
                                                << connectionString.toString()
                                                << " as a shard");
    }
    if (!isMaster) {
        return {ErrorCodes::NotMaster,
                str::stream()
                    << connectionString.toString()
                    << " does not have a master. If this is a replica set, ensure that it has a"
                    << " healthy primary and that the set has been properly initiated."};
    }

    const std::string providedSetName = connectionString.getSetName();
    const std::string foundSetName = resIsMaster["setName"].str();

    // Make sure the specified replica set name (if any) matches the actual shard's replica set
    if (providedSetName.empty() && !foundSetName.empty()) {
        return {ErrorCodes::OperationFailed,
                str::stream() << "host is part of set " << foundSetName << "; "
                              << "use replica set url format "
                              << "<setname>/<server1>,<server2>, ..."};
    }

    if (!providedSetName.empty() && foundSetName.empty()) {
        return {ErrorCodes::OperationFailed,
                str::stream() << "host did not return a set name; "
                              << "is the replica set still initializing? "
                              << resIsMaster};
    }

    // Make sure the set name specified in the connection string matches the one where its hosts
    // belong into
    if (!providedSetName.empty() && (providedSetName != foundSetName)) {
        return {ErrorCodes::OperationFailed,
                str::stream() << "the provided connection string (" << connectionString.toString()
                              << ") does not match the actual set name "
                              << foundSetName};
    }

    // Is it a config server?
    if (resIsMaster.hasField("configsvr")) {
        return {ErrorCodes::OperationFailed,
                str::stream() << "Cannot add " << connectionString.toString()
                              << " as a shard since it is a config server"};
    }

    // If the shard is part of a replica set, make sure all the hosts mentioned in the connection
    // string are part of the set. It is fine if not all members of the set are mentioned in the
    // connection string, though.
    if (!providedSetName.empty()) {
        std::set<std::string> hostSet;

        BSONObjIterator iter(resIsMaster["hosts"].Obj());
        while (iter.more()) {
            hostSet.insert(iter.next().String());  // host:port
        }

        if (resIsMaster["passives"].isABSONObj()) {
            BSONObjIterator piter(resIsMaster["passives"].Obj());
            while (piter.more()) {
                hostSet.insert(piter.next().String());  // host:port
            }
        }

        if (resIsMaster["arbiters"].isABSONObj()) {
            BSONObjIterator piter(resIsMaster["arbiters"].Obj());
            while (piter.more()) {
                hostSet.insert(piter.next().String());  // host:port
            }
        }

        for (const auto& hostEntry : connectionString.getServers()) {
            const auto& host = hostEntry.toString();  // host:port
            if (hostSet.find(host) == hostSet.end()) {
                return {ErrorCodes::OperationFailed,
                        str::stream() << "in seed list " << connectionString.toString() << ", host "
                                      << host
                                      << " does not belong to replica set "
                                      << foundSetName
                                      << "; found "
                                      << resIsMaster.toString()};
            }
        }
    }

    std::string actualShardName;

    if (shardProposedName) {
        actualShardName = *shardProposedName;
    } else if (!foundSetName.empty()) {
        // Default it to the name of the replica set
        actualShardName = foundSetName;
    }

    // Disallow adding shard replica set with name 'config'
    if (actualShardName == NamespaceString::kConfigDb) {
        return {ErrorCodes::BadValue, "use of shard replica set with name 'config' is not allowed"};
    }

    // Retrieve the most up to date connection string that we know from the replica set monitor (if
    // this is a replica set shard, otherwise it will be the same value as connectionString).
    ConnectionString actualShardConnStr = targeter->connectionString();

    ShardType shard;
    shard.setName(actualShardName);
    shard.setHost(actualShardConnStr.toString());
    shard.setState(ShardType::ShardState::kShardAware);

    return shard;
}
/* ****************************************************************************
*
* mongoConnect - 
*
* Default value for writeConcern == 1 (0: unacknowledged, 1: acknowledged)
*/
static DBClientBase* mongoConnect
(
  const char*  host,
  const char*  db,
  const char*  rplSet,
  const char*  username,
  const char*  passwd,
  bool         multitenant,
  int          writeConcern,
  double       timeout
)
{
  std::string   err;
  DBClientBase* connection = NULL;

  LM_T(LmtMongo, ("Connection info: dbName='%s', rplSet='%s', timeout=%f", db, rplSet, timeout));

  bool connected     = false;
  int  retries       = RECONNECT_RETRIES;

  if (strlen(rplSet) == 0)
  {
    // Setting the first argument to true is to use autoreconnect
    connection = new DBClientConnection(true);

    //
    // Not sure of how to generalize the following code,
    // given that DBClientBase class doesn't have a common connect() method (surprisingly)
    //
    for (int tryNo = 0; tryNo < retries; ++tryNo)
    {
      if ( ((DBClientConnection*)connection)->connect(host, err))
      {
        connected = true;
        break;
      }

      if (tryNo == 0)
      {
        LM_E(("Database Startup Error (cannot connect to mongo - doing %d retries with a %d microsecond interval)",
              retries,
              RECONNECT_DELAY));
      }
      else
      {
        LM_T(LmtMongo, ("Try %d connecting to mongo failed", tryNo));
      }

      usleep(RECONNECT_DELAY * 1000);  // usleep accepts microseconds
    }
  }
  else
  {
    LM_T(LmtMongo, ("Using replica set %s", rplSet));

    // autoReconnect is always on for DBClientReplicaSet connections.
    std::vector<std::string>  hostTokens;
    int components = stringSplit(host, ',', hostTokens);

    std::vector<HostAndPort> rplSetHosts;
    for (int ix = 0; ix < components; ix++)
    {
      LM_T(LmtMongo, ("rplSet host <%s>", hostTokens[ix].c_str()));
      rplSetHosts.push_back(HostAndPort(hostTokens[ix]));
    }

    connection = new DBClientReplicaSet(rplSet, rplSetHosts, timeout);

    //
    // Not sure of to generalize the following code,
    // given that DBClientBase class hasn't a common connect() method (surprisingly)
    //
    for (int tryNo = 0; tryNo < retries; ++tryNo)
    {
      if ( ((DBClientReplicaSet*)connection)->connect())
      {
        connected = true;
        break;
      }

      if (tryNo == 0)
      {
        LM_E(("Database Startup Error (cannot connect to mongo - doing %d retries with a %d microsecond interval)",
              retries,
              RECONNECT_DELAY));
      }
      else
      {
        LM_T(LmtMongo, ("Try %d connecting to mongo failed", tryNo));
      }

      usleep(RECONNECT_DELAY * 1000);  // usleep accepts microseconds
    }
  }

  if (connected == false)
  {
    LM_E(("Database Error (connection failed, after %d retries: '%s')", retries, err.c_str()));
    return NULL;
  }

  LM_I(("Successful connection to database"));

  //
  // WriteConcern
  //
  mongo::WriteConcern writeConcernCheck;

  //
  // In the legacy driver, writeConcern is no longer an int, but a class.
  // We need a small conversion step here
  //
  mongo::WriteConcern wc = writeConcern == 1 ? mongo::WriteConcern::acknowledged : mongo::WriteConcern::unacknowledged;

  setWriteConcern(connection, wc, &err);
  getWriteConcern(connection, &writeConcernCheck, &err);

  if (writeConcernCheck.nodes() != wc.nodes())
  {
    LM_E(("Database Error (Write Concern not set as desired)"));
    return NULL;
  }
  LM_T(LmtMongo, ("Active DB Write Concern mode: %d", writeConcern));

  /* Authentication is different depending if multiservice is used or not. In the case of not
   * using multiservice, we authenticate in the single-service database. In the case of using
   * multiservice, it isn't a default database that we know at contextBroker start time (when
   * this connection function is invoked) so we authenticate on the admin database, which provides
   * access to any database */
  if (multitenant)
  {
    if (strlen(username) != 0 && strlen(passwd) != 0)
    {
      if (!connectionAuth(connection, "admin", std::string(username), std::string(passwd), &err))
      {
        return NULL;
      }
    }
  }
  else
  {
    if (strlen(db) != 0 && strlen(username) != 0 && strlen(passwd) != 0)
    {
      if (!connectionAuth(connection, std::string(db), std::string(username), std::string(passwd), &err))
      {
        return NULL;
      }
    }
  }

  /* Get mongo version with the 'buildinfo' command */
  BSONObj     result;
  std::string extra;
  runCollectionCommand(connection, "admin", BSON("buildinfo" << 1), &result, &err);
  std::string versionString = std::string(getStringField(result, "version"));
  if (!versionParse(versionString, mongoVersionMayor, mongoVersionMinor, extra))
  {
    LM_E(("Database Startup Error (invalid version format: %s)", versionString.c_str()));
    return NULL;
  }
  LM_T(LmtMongo, ("mongo version server: %s (mayor: %d, minor: %d, extra: %s)",
                  versionString.c_str(),
                  mongoVersionMayor,
                  mongoVersionMinor,
                  extra.c_str()));

  return connection;
}
Exemple #17
0
const char* CppSQLite3Query::getStringField(const char* szField, const char* szNullValue/*=""*/)
{
	int nField = fieldIndex(szField);
	return getStringField(nField, szNullValue);
}
Exemple #18
0
StatusWith<std::set<NamespaceString>> RollbackImpl::_namespacesForOp(const OplogEntry& oplogEntry) {
    NamespaceString opNss = oplogEntry.getNamespace();
    OpTypeEnum opType = oplogEntry.getOpType();
    std::set<NamespaceString> namespaces;

    // No namespaces for a no-op.
    if (opType == OpTypeEnum::kNoop) {
        return std::set<NamespaceString>();
    }

    // CRUD ops have the proper namespace in the operation 'ns' field.
    if (opType == OpTypeEnum::kInsert || opType == OpTypeEnum::kUpdate ||
        opType == OpTypeEnum::kDelete) {
        return std::set<NamespaceString>({opNss});
    }

    // If the operation is a command, then we need to extract the appropriate namespaces from the
    // command object, as opposed to just using the 'ns' field of the oplog entry itself.
    if (opType == OpTypeEnum::kCommand) {
        auto obj = oplogEntry.getObject();
        auto firstElem = obj.firstElement();

        // Does not handle 'applyOps' entries.
        invariant(oplogEntry.getCommandType() != OplogEntry::CommandType::kApplyOps,
                  "_namespacesForOp does not handle 'applyOps' oplog entries.");

        switch (oplogEntry.getCommandType()) {
            case OplogEntry::CommandType::kRenameCollection: {
                // Add both the 'from' and 'to' namespaces.
                namespaces.insert(NamespaceString(firstElem.valuestrsafe()));
                namespaces.insert(NamespaceString(obj.getStringField("to")));
                break;
            }
            case OplogEntry::CommandType::kDropDatabase: {
                // There is no specific namespace to save for a drop database operation.
                break;
            }
            case OplogEntry::CommandType::kDbCheck:
            case OplogEntry::CommandType::kConvertToCapped:
            case OplogEntry::CommandType::kEmptyCapped: {
                // These commands do not need to be supported by rollback. 'convertToCapped' should
                // always be converted to lower level DDL operations, and 'emptycapped' is a
                // testing-only command.
                std::string message = str::stream() << "Encountered unsupported command type '"
                                                    << firstElem.fieldName()
                                                    << "' during rollback.";
                return Status(ErrorCodes::UnrecoverableRollbackError, message);
            }
            case OplogEntry::CommandType::kCreate:
            case OplogEntry::CommandType::kDrop:
            case OplogEntry::CommandType::kCreateIndexes:
            case OplogEntry::CommandType::kDropIndexes:
            case OplogEntry::CommandType::kCollMod: {
                // For all other command types, we should be able to parse the collection name from
                // the first command argument.
                try {
                    auto cmdNss = CommandHelpers::parseNsCollectionRequired(opNss.db(), obj);
                    namespaces.insert(cmdNss);
                } catch (const DBException& ex) {
                    return ex.toStatus();
                }
                break;
            }
            case OplogEntry::CommandType::kApplyOps:
            default:
                // Every possible command type should be handled above.
                MONGO_UNREACHABLE
        }
    }
/* ****************************************************************************
*
* mongoUpdateContextAvailabilitySubscription - 
*/
HttpStatusCode mongoUpdateContextAvailabilitySubscription
(
  UpdateContextAvailabilitySubscriptionRequest*   requestP,
  UpdateContextAvailabilitySubscriptionResponse*  responseP,
  Format                                          notifyFormat,
  const std::string&                              tenant
)
{
  bool reqSemTaken;

  LM_T(LmtMongo, ("Update Context Subscription, notifyFormat: '%s'", formatToString(notifyFormat)));
  reqSemTake(__FUNCTION__, "ngsi9 update subscription request", SemWriteOp, &reqSemTaken);  

  /* Look for document */
  BSONObj     sub;
  std::string err;
  OID         id;

  if (!safeGetSubId(requestP->subscriptionId, &id, &(responseP->errorCode)))
  {
    reqSemGive(__FUNCTION__, "ngsi9 update subscription request (mongo assertion exception)", reqSemTaken);
    if (responseP->errorCode.code == SccContextElementNotFound)
    {
      std::string details = std::string("invalid OID format: '") + requestP->subscriptionId.get() + "'"; 
      alarmMgr.badInput(clientIp, details);
    }
    else // SccReceiverInternalError
    {
      LM_E(("Runtime Error (exception getting OID: %s)", responseP->errorCode.details.c_str()));
    }
    return SccOk;
  }

  if (!collectionFindOne(getSubscribeContextAvailabilityCollectionName(tenant), BSON("_id" << id), &sub, &err))
  {
    reqSemGive(__FUNCTION__, "ngsi9 update subscription request (mongo db exception)", reqSemTaken);
    responseP->errorCode.fill(SccReceiverInternalError, err);
    return SccOk;
  }

  if (sub.isEmpty())
  {
     responseP->errorCode.fill(SccContextElementNotFound);
     reqSemGive(__FUNCTION__, "ngsi9 update subscription request (no subscriptions found)", reqSemTaken);
     return SccOk;
  }

  /* We start with an empty BSONObjBuilder and process requestP for all the fields that can
   * be updated. I don't like too much this strategy (I would have preferred to start with
   * a copy of the original document, then modify as neded, but this doesn't seem to be easy
   * using the API provide by the Mongo C++ driver)
   *
   * FIXME: a better implementation strategy could be doing an findAndModify() query to do the
   * update, so detecting if the document was not found, instead of using findOne() + update()
   * with $set operation. One operations to MongoDb. vs two operations.
   */
  BSONObjBuilder newSub;

  /* Entities (mandatory) */
  BSONArrayBuilder entities;
  for (unsigned int ix = 0; ix < requestP->entityIdVector.size(); ++ix) {
      EntityId* en = requestP->entityIdVector[ix];
      if (en->type == "") {
          entities.append(BSON(CASUB_ENTITY_ID << en->id <<
                               CASUB_ENTITY_ISPATTERN << en->isPattern));
      }
      else {
          entities.append(BSON(CASUB_ENTITY_ID << en->id <<
                               CASUB_ENTITY_TYPE << en->type <<
                               CASUB_ENTITY_ISPATTERN << en->isPattern));
      }

  }
  newSub.append(CASUB_ENTITIES, entities.arr());

  /* Attributes (always taken into account) */
  BSONArrayBuilder attrs;
  for (unsigned int ix = 0; ix < requestP->attributeList.size(); ++ix) {
      attrs.append(requestP->attributeList[ix]);
  }
  newSub.append(CASUB_ATTRS, attrs.arr());

  /* Duration (optional) */
  if (requestP->duration.isEmpty())
  {
    newSub.append(CASUB_EXPIRATION, getField(sub, CASUB_EXPIRATION).numberLong());
  }
  else {
      long long expiration = getCurrentTime() + requestP->duration.parse();
      newSub.append(CASUB_EXPIRATION, expiration);
      LM_T(LmtMongo, ("New subscription expiration: %l", expiration));
  }

  /* Reference is not updatable, so it is appended directly */
  newSub.append(CASUB_REFERENCE, getStringField(sub, CASUB_REFERENCE));

  int count = sub.hasField(CASUB_COUNT) ? getIntField(sub, CASUB_COUNT) : 0;

  /* The hasField check is needed due to lastNotification/count could not be present in the original doc */
  if (sub.hasField(CASUB_LASTNOTIFICATION)) {
      newSub.append(CASUB_LASTNOTIFICATION, getIntField(sub, CASUB_LASTNOTIFICATION));
  }
  if (sub.hasField(CASUB_COUNT)) {
      newSub.append(CASUB_COUNT, count);
  }

  /* Adding format to use in notifications */
  newSub.append(CASUB_FORMAT, std::string(formatToString(notifyFormat)));

  /* Update document in MongoDB */
  if (!collectionUpdate(getSubscribeContextAvailabilityCollectionName(tenant), BSON("_id" << OID(requestP->subscriptionId.get())), newSub.obj(), false, &err))
  {
    reqSemGive(__FUNCTION__, "ngsi9 update subscription request (mongo db exception)", reqSemTaken);
    responseP->errorCode.fill(SccReceiverInternalError, err);
    return SccOk;
  }

  /* Send notifications for matching context registrations */
  processAvailabilitySubscription(requestP->entityIdVector, requestP->attributeList, requestP->subscriptionId.get(), getStringField(sub, CASUB_REFERENCE), notifyFormat, tenant);

  /* Duration is an optional parameter, it is only added in the case they
   * was used for update */
  if (!requestP->duration.isEmpty())
  {
      responseP->duration = requestP->duration;
  }

  responseP->subscriptionId = requestP->subscriptionId;

  reqSemGive(__FUNCTION__, "ngsi9 update subscription request", reqSemTaken);

  return SccOk;
}
Exemple #20
0
const char* CSQLite3Query::getStringField(const char* pszField, const char* pszNullValue)
{
    int iField = fieldIndex(pszField);

    return getStringField(iField, pszNullValue);
}
const std::string SqliteQuery::getStringField(const std::string &fieldName, const std::string &nullValue)
{
    int fieldIndex = getFieldIndexByName(fieldName);
    return getStringField(fieldIndex, nullValue);
}