Exemplo n.º 1
0
NyLPC_TBool NyLPC_cMiMicIpTcpSocket_listenSyn(NyLPC_TcMiMicIpTcpSocket_t* i_inst,const struct NyLPC_TTcpSocketSynParam* i_lq,NyLPC_TUInt16 i_lport)
{
//  NyLPC_Assert(NyLPC_cMutex_isLocked(i_inst->_smutex));
    lockResource(i_inst);
    //ソケットが無効であること。
    if(i_inst->tcpstateflags==UIP_CLOSED)
    {
        //localipとdefault_mmsは別枠で設定
        /* Fill in the necessary fields for the new connection. */
        i_inst->uip_connr.current_rto32 = UIP_TCP_RTO_INITIAL;
        i_inst->uip_connr.lport = i_lport;
        i_inst->uip_connr.rport = i_lq->rport;
        i_inst->uip_connr.ripaddr=i_lq->srcaddr;
        i_inst->uip_connr.snd_nxt32=iss32;
        /* rcv_nxt should be the seqno from the incoming packet + 1. */
        i_inst->uip_connr.rcv_nxt32= i_lq->rcv_nxt32;
        //MSSの設定
        i_inst->uip_connr.peer_mss=(i_lq->mss!=0)?i_lq->mss:i_inst->uip_connr.default_mss;
        i_inst->uip_connr.peer_win=0;
        NyLPC_cFifoBuffer_clear(&(i_inst->rxbuf));
        //ここでステータスがかわる。
        i_inst->tcpstateflags = UIP_SYN_RCVD;
        //前回のデータが残っていた場合の保険
        if(i_inst->txbuf.rp!=i_inst->txbuf.wp){
            resetTxQWithUnlock(i_inst);
        }else{
            unlockResource(i_inst);
        }
        return NyLPC_TBool_TRUE;
    }
    unlockResource(i_inst);
    return NyLPC_TBool_FALSE;
}
Exemplo n.º 2
0
/**
 * 受信バッファをシークします。
 * シーク後に、遅延ACKを送出します。
 */
static void pseek(NyLPC_TiTcpSocket_t* i_inst,NyLPC_TUInt16 i_seek)
{
    void* buf;
    NyLPC_TcMiMicIpTcpSocket_t* inst=(NyLPC_TcMiMicIpTcpSocket_t*)i_inst;

    NyLPC_ArgAssert(i_seek<=NyLPC_cFifoBuffer_getLength(&(inst->rxbuf)));
    if(i_seek==0){
        return;
    }

    //ACK送信バッファの取得
    buf=NyLPC_cMiMicIpNetIf_allocSysTxBuf();

    //MUTEX LOCK
    lockResource(inst);

    //受信バッファを読み出しシーク
    NyLPC_cFifoBuffer_pop(&(inst->rxbuf),i_seek);
    //ACKパケットの生成
    setTxPacket(inst,buf,TCP_ACK,NULL,0);
    unlockResource(inst);
    //ACK送信
    NyLPC_cMiMicIpNetIf_sendIPv4Tx(buf);
    NyLPC_cMiMicIpNetIf_releaseTxBuf(buf);

}
Exemplo n.º 3
0
/**
 * 空きキューを1個返します。
 * 空きキューの
 */
static struct NyLPC_TcTcpSocket_TxQItem* getTxQ(NyLPC_TcMiMicIpTcpSocket_t* i_inst,NyLPC_TcStopwatch_t* i_timer)
{
    int i;
    struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
    do{
        //クローズドに遷移してしまったら、エラーである。
        if(i_inst->tcpstateflags==UIP_CLOSED){
            return NULL;
        }
        //キューの空きをチェック。wp+1==rpなら、キューがいっぱい。rp==wpなら、キューが空。
        if(((i_inst->txbuf.wp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ)==i_inst->txbuf.rp){
            //一時的なアンロック
            unlockResource(i_inst);
            //タスクスイッチ
            NyLPC_cThread_yield();
            //ロック
            lockResource(i_inst);
            continue;
        }
        i=i_inst->txbuf.wp;
        i_inst->txbuf.wp=(i+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
        return &(q[i]);
    }while(!NyLPC_cStopwatch_isExpired(i_timer));
    //失敗。タイムアウト。
    return NULL;
}
Exemplo n.º 4
0
/**
 * 事前にAllocしたTxパケットを送信します。
 * このAPIはゼロコピー送信をサポートするためのものです。
 * @param i_buf_ptr
 * allocSendBufで取得したメモリを指定します。
 * @return
 * 関数が失敗した場合、i_buf_ptrは「開放されません。」
 */
static NyLPC_TBool psend(NyLPC_TiTcpSocket_t* i_inst,void* i_buf_ptr,int i_len,NyLPC_TUInt32 i_wait_in_msec)
{
	NyLPC_TcMiMicIpTcpSocket_t* inst=(NyLPC_TcMiMicIpTcpSocket_t*)i_inst;
    struct NyLPC_TcTcpSocket_TxQItem* txq;
    void* buf;
    NyLPC_TcStopwatch_t sw;
    //ESTABLISHEDでなければエラー
    if(inst->tcpstateflags!=UIP_ESTABLISHED){
        //ESTABLISHEDでなければエラー
        return NyLPC_TBool_FALSE;
    }
    //送信データ0なら何もしない。
    if(i_len<1){
        releaseSendBuf(i_inst,i_buf_ptr);
        return NyLPC_TBool_TRUE;
    }
    NyLPC_cStopwatch_initialize(&sw);
    NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);

    //先頭ポインタは、i_buf-sizeof(SIZE_OF_IPv4_TCPIP_HEADER)固定
    buf=(NyLPC_TUInt8*)i_buf_ptr-SIZE_OF_IPv4_TCPIP_HEADER;
    lockResource(inst);
    //送信キューの取得
    txq=getTxQ(inst,&sw);
    //送信キューが取れなかった。
    if(txq==NULL){
        //シーケンス番号をロールバックできないので、エラーとする。
        unlockResource(inst);
        NyLPC_cStopwatch_finalize(&sw);
        return NyLPC_TBool_FALSE;
    }
    //ここから先はi_bufの所有権はインスタンスになってる。

    //IPv4ペイロードの書き込み

    //allocをした時点でwin,mssは考慮されているので、そのままそうしんしる。

    //ACK番号の計算
    txq->rto32=inst->uip_connr.current_rto32;
    txq->tick_of_sent=NyLPC_cStopwatch_now();
    //パケットヘッダの生成(ヘッダ長はpreadで定義した値(4+6)*4=40です。)
    setTxPacketHeader(inst,buf,TCP_ACK|TCP_PSH,i_len);
    txq->packet=buf;

    //シーケンス番号の更新
    inst->uip_connr.snd_nxt32=inst->uip_connr.snd_nxt32+i_len;
    //Peerのウインドウサイズを更新
    inst->uip_connr.peer_win-=i_len;
    //ACK番号の返却
    txq->ackno=NyLPC_HTONL(inst->uip_connr.snd_nxt32);
    unlockResource(inst);
    NyLPC_cMiMicIpNetIf_sendIPv4Tx(buf);
    NyLPC_cStopwatch_finalize(&sw);
    return NyLPC_TBool_TRUE;
}
Exemplo n.º 5
0
void Player_SID::reserveChannel(int channel, uint8 prioValue, int chanResIndex) { // $4ffe
	if (channel == 3) {
		filterUsed = true;
	} else if (channel < 3) {
		usedChannelBits |= BITMASK[channel];
		countFreeChannels();
	}

	chanPrio[channel] = prioValue;
	lockResource(chanResIndex);
}
Exemplo n.º 6
0
Arquivo: ion.c Projeto: b/ION
static void	writeMemoToIonLog(char *text)
{
	static ResourceLock	logFileLock;
	static char		ionLogFileName[264] = "";
	static int		ionLogFile = -1;
	time_t			currentTime = getUTCTime();
	char			timestampBuffer[20];
	int			textLen;
	static char		msgbuf[256];

	if (text == NULL) return;

	/*	The log file is shared, so access to it must be
	 *	mutexed.						*/

	if (initResourceLock(&logFileLock) < 0)
	{
		return;
	}

	lockResource(&logFileLock);
	if (ionLogFile == -1)
	{
		if (ionLogFileName[0] == '\0')
		{
			isprintf(ionLogFileName, sizeof ionLogFileName,
					"%.255s%cion.log",
					getIonWorkingDirectory(),
					ION_PATH_DELIMITER);
		}

		ionLogFile = open(ionLogFileName, O_WRONLY | O_APPEND | O_CREAT,
				00666);
		if (ionLogFile == -1)
		{
			unlockResource(&logFileLock);
			perror("Can't redirect ION error msgs to log");
			return;
		}
	}

	writeTimestampLocal(currentTime, timestampBuffer);
	isprintf(msgbuf, sizeof msgbuf, "[%s] %s\n", timestampBuffer, text);
	textLen = strlen(msgbuf);
	if (write(ionLogFile, msgbuf, textLen) < 0)
	{
		perror("Can't write ION error message to log file");
	}
#ifdef TargetFFS
	close(ionLogFile);
	ionLogFile = -1;
#endif
	unlockResource(&logFileLock);
}
Exemplo n.º 7
0
/**
 * uipサービスタスクが実行する関数です。
 * 定期的に実行する関数。最低でも1s単位で実行してください。
 */
void NyLPC_cMiMicIpTcpSocket_periodic(
	NyLPC_TcMiMicIpTcpSocket_t* i_inst)
{
    int i;
    struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
    NyLPC_TcStopwatch_t sw;
    NyLPC_TUInt32 now;
    int rp;
    NyLPC_cStopwatch_initialize(&sw);
    now=NyLPC_cStopwatch_now();
    //MUTEX LOCK
    lockResource(i_inst);
    if(i_inst->tcpstateflags==UIP_CLOSED)
    {
        //CLOSEDなら、バッファ開放。
        resetTxQWithUnlock(i_inst);
    }else if(i_inst->txbuf.rp==i_inst->txbuf.wp){
        //再送信パケットがなければ何もしないよ。
        unlockResource(i_inst);
    }else if(i_inst->uip_connr.peer_win==0){
        //peer_winが0の場合は何もしない。
        unlockResource(i_inst);
    }else{
        //再送信処理
        rp=i_inst->txbuf.rp;
        NyLPC_cStopwatch_set(&sw,q[rp].tick_of_sent);
        if(NyLPC_cStopwatch_elapseInMsec(&sw)>q[rp].rto32){
            //最古のパケットの送信時間をチェックして、タイムアウトが発生したら、再送時間と送信時刻をセット
            //最古パケットRTOを2倍。
            q[rp].rto32*=2;
            for(i=rp;i!=i_inst->txbuf.wp;i=(i+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ){
                q[i].tick_of_sent=now;
            }
            if(q[rp].rto32>UIP_IP_RTO_MAX_RTO){
                //最古のRTOが64秒を超えたら、CLOSED
                i_inst->tcpstateflags =UIP_CLOSED;
                resetTxQWithUnlock(i_inst);
                sendRst(i_inst);
            }else{
                //規定時間内なら、再送処理
                for(i=rp;i!=i_inst->txbuf.wp;i=(i+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ){
//                  NyLPC_cUipService_sendIPv4Tx(NyLPC_cIPv4Payload_getBuf(&(q[i].data)));
                    NyLPC_cMiMicIpNetIf_sendIPv4Tx(q[i].packet);
                }
                unlockResource(i_inst);
            }
        }else{
            unlockResource(i_inst);
        }
    }
    NyLPC_cStopwatch_finalize(&sw);
    return;
}
Exemplo n.º 8
0
/**
 * sq番のTxがキューから消え去るのを待ちます。
 * この関数は、アンロック状態でコールしてください。
 * <div>
 * パケットがキューからなくなる条件は、以下の2つです。
 * <ul>
 * <li>ACKを受信してパケットキューが更新された。</li>
 * <li>RSTを受信して(CLOSEDに遷移して)、キューがクリアされた。</li>
 * <li>送信タイムアウトで関数が(CLOSEDに遷移させて)キューをクリアした。</li>
 * </ul>
 * </div>
 * @param i_wait_msec
 * @return
 * 1番目の条件でパケットが消失したときのみ、TRUEを返します。
 * 失敗した場合、TCPステータスがCLOSEDでなければ、RSTを送信してステータスをCLOSEDにします。
 */
static NyLPC_TBool waitForTxRemove(NyLPC_TcMiMicIpTcpSocket_t* i_inst,NyLPC_TUInt32 i_sq,NyLPC_TcStopwatch_t* i_timer)
{
    NyLPC_TUInt8 f;
    lockResource(i_inst);
    do{
        //パケットが送信中か調べる。
        if(!isPacketAcked(i_inst,i_sq)){
            //まだある場合は、タスクスイッチを繰り返して消失を待つ。
            unlockResource(i_inst);
            NyLPC_cThread_yield();
            lockResource(i_inst);
            continue;
        }
        //なくなった場合は、原因を調べる。
        f=i_inst->tcpstateflags;
        unlockResource(i_inst);
        return (f==UIP_CLOSED)?NyLPC_TBool_FALSE:NyLPC_TBool_TRUE;
    }while(!NyLPC_cStopwatch_isExpired(i_timer));
    unlockResource(i_inst);
    return NyLPC_TBool_FALSE;
}
Exemplo n.º 9
0
/**
 * uipサービスタスクが実行する関数です。
 * サービスの停止を通知します。
 */
void NyLPC_cMiMicIpTcpSocket_stopService(NyLPC_TcMiMicIpTcpSocket_t* i_inst)
{
    lockResource(i_inst);
    if(i_inst->tcpstateflags==UIP_CLOSED)
    {
        unlockResource(i_inst);
    }else{
        i_inst->tcpstateflags=UIP_CLOSED;
        resetTxQWithUnlock(i_inst);
        sendRst(i_inst);
    }
    return;
}
Exemplo n.º 10
0
int mgr_agent_remove(eid_t* in_eid)
{
	agent_t 	*agent 		= NULL;
	Object 		*entry		= NULL;
	LystElt		elt;

	DTNMP_DEBUG_ENTRY("mgr_agent_remove","(0x%#llx)", (unsigned long) in_eid);

	/* Step 0: Sanity Checks. */
	if(in_eid == NULL)
	{
		DTNMP_DEBUG_ERR("remove_agent","Specified EID was null.", NULL);
		DTNMP_DEBUG_EXIT("remove_agent","", NULL);
		return -1;
	}

	lockResource(&agents_mutex);

	elt = lyst_first(known_agents);
	while(elt != NULL)
	{
		if(strcmp(in_eid->name, ((agent_t *) lyst_data(elt))->agent_eid.name) == 0)
		{
			agent = (agent_t *) lyst_data(elt);
			lyst_delete(elt);
			break;
		}
		else
		{
			elt = lyst_next(elt);
		}
	}

	unlockResource(&agents_mutex);

	if(agent == NULL)
	{
		DTNMP_DEBUG_ERR("remove_agent", "No agent %s found in hashtable", in_eid->name);
		DTNMP_DEBUG_EXIT("remove_agent", "->0", NULL);
		return 0;
	}

	rpt_clear_lyst(&(agent->reports), &(agent->mutex), 1);
	def_lyst_clear(&(agent->custom_defs), &(agent->mutex), 1);

	killResourceLock(&(agent->mutex));
	MRELEASE(agent);

	DTNMP_DEBUG_EXIT("remove_agent", "->1", NULL);
	return 1;
}
Exemplo n.º 11
0
int msg_rx_data_rpt(eid_t *sender_eid, uint8_t *cursor, uint32_t size, uint32_t *bytes_used)
{
    agent_t *agent = NULL;
    int result = -1;

	DTNMP_DEBUG_ENTRY("msg_rx_data_rpt","()",NULL);


	/* Step 0: Sanity Check */
	if((sender_eid == NULL) || (cursor == NULL) || (bytes_used == NULL))
	{
		DTNMP_DEBUG_ERR("msg_rx_data_rpt","Bad Parms", NULL);
		DTNMP_DEBUG_EXIT("msg_rx_data_rpt","-->-1",NULL);
		return -1;
	}

	DTNMP_DEBUG_ALWAYS("msg_rx_data_rpt", "Processing a data report.\n", NULL);
	*bytes_used = 0;

	/* Step 1: Retrieve stored information about this agent. */
	if((agent = mgr_agent_get(sender_eid)) == NULL)
	{
		DTNMP_DEBUG_WARN("msg_rx_data_rpt",
				         "Received group is from an unknown sender (%s); ignoring it.",
				         sender_eid->name);
	}
	else
	{
		rpt_data_t *report = NULL;

		if((report = rpt_deserialize_data(cursor, size, bytes_used)) == NULL)
		{
			DTNMP_DEBUG_ERR("msg_rx_data_rpt","Can't deserialize rpt",NULL);
		}
		else
		{
			/* Step 1.1: Add the report. */
			lockResource(&(agent->mutex));
			lyst_insert_last(agent->reports, report);
			unlockResource(&(agent->mutex));

			result = 0;

			/* Step 1.2: Update statistics. */
			g_reports_total++;
		}
	}

	DTNMP_DEBUG_EXIT("msg_rx_data_rpt","-->%d", result);
	return result;
}
Exemplo n.º 12
0
AEResult GameResourceManager::ManageGameResource(GameResource* gameResource, const std::wstring& stringID, bool keepAlive)
{
	AEAssert(gameResource != nullptr);
	if(gameResource == nullptr)
	{
		return AEResult::NullParameter;
	}

	std::lock_guard<std::mutex> lock(m_GameResourceManagerMutex);
	std::lock_guard<std::mutex> lockResource(gameResource->m_GameResourceMutex);

	if(gameResource->IsManaged())
	{
		return AEResult::ResourceIsManaged;
	}

	if(GameResourceExists(gameResource->GetUniqueID()))
	{
		return AEResult::ObjExists;
	}

	if(!stringID.empty())
	{
		if(GameResourceStringIDExists(stringID))
		{
			uint64_t id = m_StringIDToGameResource[stringID];

			if(GameResourceExists(id))
			{
				std::wstring msgerr = fmt::format(AELOCMAN->GetLiteral(L"GAME_RESOURCE_STR_ID_EXISTS_ERR_MSG"), __FUNCTIONW__, stringID);
				AELOGGER->AddNewLog(LogLevel::Error, msgerr);

				return AEResult::ObjExists;
			}
		}
	}

	gameResource->m_ReleaseCallback		= std::bind(&GameResourceManager::GameResourceReleaseCallback, this, std::placeholders::_1, std::placeholders::_2);
	gameResource->m_Managed				= true;
	gameResource->m_KeepAlive			= keepAlive;
	gameResource->m_StringIdentifier	= stringID;

	m_GameResourceMap[gameResource->GetUniqueID()] = gameResource;

	if(!stringID.empty())
	{
		m_StringIDToGameResource[stringID] = gameResource->GetUniqueID();
	}

	return AEResult::Ok;
}
Exemplo n.º 13
0
/**
 * この関数は、ソケットの受信バッファの読み取り位置と、読み出せるデータサイズを返却します。
 * 関数はポインターを返却するだけで、バッファの読み取り位置をシークしません。
 * シークするにはNyLPC_cTcpSocket_pseekを使います。
 */
static NyLPC_TInt32 precv(NyLPC_TiTcpSocket_t* i_inst,const void** o_buf_ptr,NyLPC_TUInt32 i_wait_msec)
{
	NyLPC_TcMiMicIpTcpSocket_t* inst=(NyLPC_TcMiMicIpTcpSocket_t*)i_inst;
    volatile NyLPC_TUInt8 st;
    NyLPC_TUInt16 rlen;
    //タイマを生成
    NyLPC_TcStopwatch_t sw;
    NyLPC_cStopwatch_initialize(&sw);

    //ESTABLISHED以外の場合は、エラー。
    NyLPC_cStopwatch_setNow(&sw);
    do{
        //読み出しバッファ情報のコピー
        //MUTEX LOCK
        lockResource(inst);
        st=inst->tcpstateflags;
        rlen=NyLPC_cFifoBuffer_getLength(&(inst->rxbuf));
        *o_buf_ptr=NyLPC_cFifoBuffer_getPtr(&(inst->rxbuf));
        //MUTEX UNLOCK
        unlockResource(inst);

        //バッファが空の場合は、ステータスチェック。ESTABLISHEDでなければ、エラー(PASVCLOSE等の場合)
        switch(st){
        case UIP_ESTABLISHED:
            if(rlen>0){
                //バッファにパケットがあれば返却
                NyLPC_cStopwatch_finalize(&sw);
                return rlen;
            }
            break;
        case UIP_CLOSE_WAIT:
            if(rlen>0){
                //バッファにパケットがあれば返却
                NyLPC_cStopwatch_finalize(&sw);
                return rlen;
            }
            //引き続きエラー処理
        default:
            //他の場合はエラー
            NyLPC_cStopwatch_finalize(&sw);
            return -1;
        }
        //タスクスイッチ
        NyLPC_cThread_yield();
    }while(NyLPC_cStopwatch_elapseInMsec(&sw)<i_wait_msec);
    //規定時間内に受信が成功しなかった。
    NyLPC_cStopwatch_finalize(&sw);
    return 0;
}
Exemplo n.º 14
0
/**
 * \brief Cleans up a lyst of data reports.
 *
 * \author Ed Birrane
 *
 * \param[in,out] reportLyst  THe lyst to be cleared.
 */
void rpt_clear_lyst(Lyst *list, ResourceLock *mutex, int destroy)
{
    LystElt elt;
    rpt_data_t *cur_rpt = NULL;

    DTNMP_DEBUG_ENTRY("rpt_clear_lyst","(0x%x, 0x%x, %d)",
			          (unsigned long) list, (unsigned long) mutex, destroy);

    if((list == NULL) || (*list == NULL))
    {
    	DTNMP_DEBUG_ERR("rpt_clear_lyst","Bad Params.", NULL);
    	return;
    }

    if(mutex != NULL)
    {
    	lockResource(mutex);
    }

    /* Free any reports left in the reports list. */
    for (elt = lyst_first(*list); elt; elt = lyst_next(elt))
    {
        /* Grab the current report */
        if((cur_rpt = (rpt_data_t*) lyst_data(elt)) == NULL)
        {
        	DTNMP_DEBUG_WARN("rpt_clear_lyst","Can't get report from lyst!", NULL);
        }
        else
        {
        	rpt_release_data(cur_rpt);
        }
    }

    lyst_clear(*list);

    if(destroy != 0)
    {
    	lyst_destroy(*list);
    	*list = NULL;
    }

    if(mutex != NULL)
    {
    	unlockResource(mutex);
    }

    DTNMP_DEBUG_EXIT("rpt_clear_lyst","->.", NULL);
}
Exemplo n.º 15
0
void ctrl_clear_lyst(Lyst *list, ResourceLock *mutex, int destroy)
{
	LystElt elt;
	ctrl_exec_t *entry = NULL;

	AMP_DEBUG_ENTRY("ctrl_clear_lyst","(0x%x, 0x%x, %d)",
			          (unsigned long) list, (unsigned long) mutex, destroy);

    if((list == NULL) || (*list == NULL))
    {
    	AMP_DEBUG_ERR("ctrl_clear_lyst","Bad Params.", NULL);
    	return;
    }

	if(mutex != NULL)
	{
		lockResource(mutex);
	}

	/* Free any reports left in the reports list. */
	for (elt = lyst_first(*list); elt; elt = lyst_next(elt))
	{
		/* Grab the current item */
		if((entry = (ctrl_exec_t *) lyst_data(elt)) == NULL)
		{
			AMP_DEBUG_ERR("ctrl_clear_lyst","Can't get report from lyst!", NULL);
		}
		else
		{
			ctrl_release(entry);
		}
	}

	lyst_clear(*list);

	if(destroy != 0)
	{
		lyst_destroy(*list);
		*list = NULL;
	}

	if(mutex != NULL)
	{
		unlockResource(mutex);
	}

	AMP_DEBUG_EXIT("ctrl_clear_lyst","->.",NULL);
}
Exemplo n.º 16
0
agent_t* mgr_agent_get(eid_t* in_eid)
{
	Object 	 *entry 		= NULL;
	agent_t *agent			= NULL;

	DTNMP_DEBUG_ENTRY("mgr_agent_get","(0x%#llx)", (unsigned long) in_eid);

	/* Step 0: Sanity Check. */
	if(in_eid == NULL)
	{
		DTNMP_DEBUG_ERR("mgr_agent_get","Null argument", NULL);
		DTNMP_DEBUG_EXIT("mgr_agent_get", "->NULL", NULL);
		return NULL;
	}

	/* Step 1: Lock agent mutex, walk list looking for match. */
	lockResource(&agents_mutex);

	LystElt elt = lyst_first(known_agents);
	while(elt != NULL)
	{
		agent = (agent_t *) lyst_data(elt);
		if(strcmp(in_eid->name, agent->agent_eid.name) == 0)
		{
			break;
		}
		else
		{
			agent = NULL;
			elt = lyst_next(elt);
		}
	}

	unlockResource(&agents_mutex);

	if(agent == NULL)
	{
		DTNMP_DEBUG_EXIT("mgr_agent_get", "->NULL", NULL);
	}
	else
	{
		DTNMP_DEBUG_EXIT("mgr_agent_get","->Agent %s", agent->agent_eid.name);
	}

	return agent;
}
Exemplo n.º 17
0
/**
 * RSTを1フレームだけ送信します。
 * この関数は、クローズドステータスのソケットにしてからコールします。
 * この関数は、アンロック状態でコールしてね。
 */
static void sendRst(NyLPC_TcMiMicIpTcpSocket_t* i_inst)
{
    void* buf;

    NyLPC_Assert(i_inst->tcpstateflags==UIP_CLOSED);
    //ペイロードライタの初期化

    //@bug バッファが取れるまで通信がブロックするの。ここはなんとかしないと。
    buf=NyLPC_cMiMicIpNetIf_allocSysTxBuf();
    lockResource(i_inst);
    i_inst->uip_connr.snd_nxt32++;
    unlockResource(i_inst);
    setTxPacket(i_inst,buf,TCP_RST|TCP_ACK,NULL,0);
    NyLPC_cMiMicIpNetIf_sendIPv4Tx(buf);
    NyLPC_cMiMicIpNetIf_releaseTxBuf(buf);
    NyLPC_cIPv4Payload_finalize(&ipv4);
    return;
}
Exemplo n.º 18
0
/**
 * この関数は、UIP_SYN_RCVDステータスのソケットを、ESTABLISHEDへ遷移させます。
 * cTcpListener_listen関数を通過したインスタンスに実行してください。
 * この関数は、アプリケーションが呼び出します。
 * @return
 *
 */
static NyLPC_TBool accept(NyLPC_TiTcpSocket_t* i_inst,NyLPC_TUInt32 i_wait_in_msec)
{
    volatile NyLPC_TUInt8 f;
	NyLPC_TcMiMicIpTcpSocket_t* inst=(NyLPC_TcMiMicIpTcpSocket_t*)i_inst;
	NyLPC_TUInt32 sq;
    NyLPC_TcStopwatch_t sw;

    NyLPC_cStopwatch_initialize(&sw);
    //ステータスチェック
    f=inst->tcpstateflags;
    switch(f)
    {
    case UIP_ESTABLISHED:
        return NyLPC_TBool_TRUE;
    case UIP_SYN_RCVD:
        //処理対象
        break;
    default:
        return NyLPC_TBool_FALSE;
    }
    NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
    if(sendWithRetransmit(inst,TCP_SYN|TCP_ACK,NULL,0,&sw,&sq)==0){
        //ちょっと待つ。
        NyLPC_cThread_yield();
        //キューにあるTXが消えるのを待つ。
        if(waitForTxRemove(inst,sq,&sw)){
            //ACK受信に成功して、TXが消失
            NyLPC_cStopwatch_finalize(&sw);
            return NyLPC_TBool_TRUE;
        }
    }
    //ロックして、強制的なステータス遷移
    lockResource(inst);
    f=inst->tcpstateflags;
    if(f!=UIP_CLOSED){
        //もし、強制CLOSE遷移であれば、RSTも送信。
    	inst->tcpstateflags=UIP_CLOSED;
        unlockResource(inst);
        sendRst(inst);
    }else{
        unlockResource(inst);
    }
    return NyLPC_TBool_FALSE;
}
Exemplo n.º 19
0
/**
 * Public function
 */
static void finalize(NyLPC_TiTcpSocket_t* i_inst)
{
    int i;
	NyLPC_TcMiMicIpTcpSocket_t* inst=(NyLPC_TcMiMicIpTcpSocket_t*)i_inst;
    NyLPC_Assert(NyLPC_cMiMicIpNetIf_isInitService());
    //開放漏れの保険
    if(inst->txbuf.rp!=inst->txbuf.wp){
        lockResource(inst);
        resetTxQWithUnlock(inst);
    }
    for(i=0;i<NyLPC_TcTcpSocket_NUMBER_OF_TXQ;i++){
    	inst->txbuf.txq[i].packet=NULL;
    }
    NyLPC_cFifoBuffer_finalize(&(inst->rxbuf));
//  NyLPC_cMutex_finalize(&(i_inst->_smutex));
    NyLPC_cMiMicIpNetIf_releaseTcpSocketMemory(inst);

    return;
}
Exemplo n.º 20
0
void Player_SID::initMusic(int songResIndex) { // $7de6
	unlockResource(resID_song);

	resID_song = songResIndex;
	_music = getResource(resID_song);
	if (_music == NULL) {
		return;
	}

	// song base address
	uint8* songFileDataPtr = _music;
	actSongFileData = _music;

	initializing = true;
	_soundInQueue = false;
	isMusicPlaying = false;

	unlockCodeLocation();
	resetPlayerState();

	lockResource(resID_song);
	buildStepTbl(songFileDataPtr[5]);

	// fetch sound
	songChannelBits = songFileDataPtr[4];
	for (int i = 2; i >= 0; --i) {
		if ((songChannelBits & BITMASK[i]) != 0) {
			func_7eae(i, songFileDataPtr);
		}
	}

	isMusicPlaying = true;
	lockCodeLocation();

	SIDReg23 &= 0xf0;
	SID_Write(23, SIDReg23);

	handleMusicBuffer();

	initializing = false;
	_soundInQueue = true;
}
Exemplo n.º 21
0
AEResult GameResourceManager::UnManageGameResource(uint64_t id)
{
	std::lock_guard<std::mutex> lock(m_GameResourceManagerMutex);

	if(!GameResourceExists(id))
	{
		return AEResult::NotFound;
	}

	GameResource* gameResource = m_GameResourceMap[id];
	
	std::lock_guard<std::mutex> lockResource(gameResource->m_GameResourceMutex);

	gameResource->m_Managed = false;
	gameResource->m_ReleaseCallback = nullptr;
	gameResource->m_KeepAlive = false;
	gameResource->m_StringIdentifier = L"";

	m_GameResourceMap.erase(m_GameResourceMap.find(id));

	return AEResult::Ok;
}
Exemplo n.º 22
0
int mgr_agent_add(eid_t agent_eid)
{
	int result = -1;
	agent_t *agent = NULL;

	DTNMP_DEBUG_ENTRY("mgr_agent_add","(%s)", agent_eid.name);

	lockResource(&agents_mutex);

	/* Check if the agent is already known. */
	if((agent = mgr_agent_get(&agent_eid)) != NULL)
	{
		unlockResource(&agents_mutex);
		result = 0;
		DTNMP_DEBUG_ERR("mgr_agent_add","Trying to add an already-known agent.", NULL);
		DTNMP_DEBUG_EXIT("mgr_agent_add","->%d.", result);

		return result;
	}

	/* Create and store the new agent. */
	if((agent = mgr_agent_create(&agent_eid)) == NULL)
	{
		unlockResource(&agents_mutex);

		DTNMP_DEBUG_ERR("mgr_agent_add","Failed to create agent.", NULL);
		DTNMP_DEBUG_EXIT("mgr_agent_add","->%d.", result);

		return result;
	}

	DTNMP_DEBUG_INFO("mgr_agent_add","Registered agent: %s", agent_eid.name);
	unlockResource(&agents_mutex);

	result = 1;
	DTNMP_DEBUG_EXIT("mgr_agent_add","->%d.", result);
	return result;
}
Exemplo n.º 23
0
void mgr_agent_remove_cb(LystElt elt, void *nil)
{
	eid_t   *agent_eid	= NULL;
	agent_t	*agent		= NULL;
	Object	*entry		= NULL;

	if(elt == NULL)
	{
		DTNMP_DEBUG_ERR("mgr_agent_remove_cb",
				        "Specified Lyst element was null.", NULL);
		DTNMP_DEBUG_EXIT("mgr_agent_remove_cb","", NULL);
		return;
	}

	lockResource(&agents_mutex);

	if((agent = (agent_t *) lyst_data(elt)) == NULL)
	{
		DTNMP_DEBUG_ERR("mgr_agent_remove_cb",
				        "Specified Lyst data was null.", NULL);
	}
	else
	{
		rpt_clear_lyst(&(agent->reports), &(agent->mutex), 1);
		def_lyst_clear(&(agent->custom_defs), &(agent->mutex), 1);

		killResourceLock(&(agent->mutex));
		MRELEASE(agent);
	}

	unlockResource(&agents_mutex);

	DTNMP_DEBUG_EXIT("mgr_agent_remove_cb","", NULL);

	return;
}
Exemplo n.º 24
0
bool LabrestAPI::LabrestDB::lockResource(int resourceId, ::std::string username, int duration)
{
//    ::std::cout << "LabrestDB::lockResource()  called" << ::std::endl;
    
    bool status;
    
    int lock_st_id; 

    sqlite3_stmt *ppStmt;
    
    sqlite3_exec(db, "BEGIN", 0, 0, 0);
    
    if (ExistsResource(resourceId))
    {    
    if (ResourceIsNotLock(resourceId))
    {
        sqlite3_prepare(db,"insert into using_resource(username,resource_id, "
                "start_time, duration, end_time) "
               "values(?,?,datetime(), ?, ?);" ,-1,&ppStmt,0);
       
        sqlite3_bind_text(ppStmt,1,username.c_str(),username.length(),NULL);

        sqlite3_bind_int(ppStmt, 2, resourceId);
        
        if (duration == -1) sqlite3_bind_null(ppStmt,3);
            else sqlite3_bind_int(ppStmt, 3, duration);
        
        sqlite3_bind_null(ppStmt,4);
        
        if (sqlite3_step(ppStmt) == SQLITE_DONE)
        {
            status = true;
        }
        else
        {
            status = false;
        }
        sqlite3_finalize(ppStmt);
    
        if (status)
         
            {
                sqlite3_prepare(db,"update resource set lock_status = "
                        "(select id from using_resource where "
                     "resource_id = ? and end_time isnull)"
                        " where id = ?;" ,-1,&ppStmt,0);
                
                sqlite3_bind_int(ppStmt, 1, resourceId);
                
                sqlite3_bind_int(ppStmt, 2, resourceId);
                
                if (sqlite3_step(ppStmt) == SQLITE_DONE)
                {
                    status = true;
                }
                else
                {
                    status = false;
                }
                sqlite3_finalize(ppStmt);
                
                sqlite3_prepare(db,"select id from resource where parent = ?;" ,-1,&ppStmt,0);
                                
                sqlite3_bind_int(ppStmt, 1, resourceId);
                
                while (sqlite3_step(ppStmt) == SQLITE_ROW)
                {
                    lockResource(sqlite3_column_int(ppStmt,0), username, duration);
                }
                sqlite3_finalize(ppStmt);          
        }
        
        Event ev;
    
        ev.TypeEvent = CB_LOCK;
        ev.id = EvQueuePtr->next_id;
        ev.resourceId = resourceId;
        ev.userDest = "";
        ev.userSrc = username;
    
        EvQueuePtr->push_back(ev);
        
        sqlite3_exec(db, "COMMIT", 0, 0, 0);
    }
    else
    {
        sqlite3_exec(db, "COMMIT", 0, 0, 0);
        
        ::LabrestAPI::ResourceIsLock rl;
        
        rl.ice_throw();
    }
    }
    else
    {
        sqlite3_exec(db, "COMMIT", 0, 0, 0);
        
        ::LabrestAPI::InvalidValue iv;
        
        iv.ice_throw();
    }
    
    return status;
}
Exemplo n.º 25
0
static void close(NyLPC_TiTcpSocket_t* i_inst,NyLPC_TUInt32 i_wait_in_msec)
{
	NyLPC_TcMiMicIpTcpSocket_t* inst=(NyLPC_TcMiMicIpTcpSocket_t*)i_inst;
    NyLPC_TcStopwatch_t sw;
    volatile NyLPC_TUInt8 f;
    NyLPC_TUInt32 sq;
    NyLPC_cStopwatch_initialize(&sw);
    NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
    lockResource(inst);

    f=inst->tcpstateflags;
    //ステータスチェック
    switch(f)
    {
    case UIP_CLOSED:
        //閉じている。
        goto ReturnWithUnlock;
    case UIP_ESTABLISHED:
        //アクティブクローズ。
    	inst->tcpstateflags=UIP_FIN_WAIT_1;
        //送信のために一旦解除
        unlockResource(inst);
        //FINの送信
        if(sendWithRetransmit(inst,TCP_FIN|TCP_ACK,NULL,0,&sw,&sq)==0){
            //ちょっと待つ。
            NyLPC_cThread_yield();
            //TXの消去待ち
            if(waitForTxRemove(inst,sq,&sw)){
                //再ロック
                lockResource(inst);
                //タイムアウトするか、UIP_CLOSED、もしくはTIME_WAITに遷移するのを待つ。(遷移はRxprocで自動的に実行。)
                do{
                    switch(inst->tcpstateflags)
                    {
                    case UIP_TIME_WAIT:
                    	inst->tcpstateflags=UIP_CLOSED;
                    case UIP_CLOSED:
                        NyLPC_Assert(inst->txbuf.rp==inst->txbuf.wp);
                        //成功。
                        goto ReturnWithUnlock;
                    case UIP_FIN_WAIT_1:
                    case UIP_FIN_WAIT_2:
                    case UIP_CLOSING:
                        //一時的なアンロック
                        unlockResource(inst);
                        NyLPC_cThread_yield();
                        lockResource(inst);
                    default:
                        break;
                    }
                }while(!NyLPC_cStopwatch_isExpired(&sw));
                unlockResource(inst);
            }
        }
        break;
    case UIP_CLOSE_WAIT:
        //LAST_ACKへ遷移
    	inst->tcpstateflags=UIP_LAST_ACK;
        //送信のために一旦解除
        unlockResource(inst);
        if(sendWithRetransmit(inst,TCP_FIN|TCP_ACK,NULL,0,&sw,&sq)==0){
            //ちょっと待つ。
            NyLPC_cThread_yield();
            //TXの消去待ち
            if(waitForTxRemove(inst,sq,&sw)){
                //再ロック
                lockResource(inst);
                //TX消去後にCLOSEDに遷移していればOK
                if(inst->tcpstateflags==UIP_CLOSED)
                {
                    NyLPC_Assert(inst->txbuf.rp==inst->txbuf.wp);
                    goto ReturnWithUnlock;
                }
                unlockResource(inst);
            }
        }
        //エラー。RSTで切断。
        break;
    default:
        unlockResource(inst);
        NyLPC_Warning();
        break;
    }
//  if(i_inst->_smutex._lock_count>0){
//      NyLPC_Warning();
//  }
    //このパスに到達するのは、FIN送信/ACKに成功したにも拘らず、規定時間内にCLOSEDに遷移しなかった場合。
    //コネクションを強制遷移して、RST
    lockResource(inst);
    f=inst->tcpstateflags;
    if(f!=UIP_CLOSED){
        //もし、強制CLOSE遷移であれば、RSTも送信。
    	inst->tcpstateflags=UIP_CLOSED;
        unlockResource(inst);
        sendRst(inst);
    }else{
        unlockResource(inst);
    }
    NyLPC_cStopwatch_finalize(&sw);
    return;
ReturnWithUnlock:
    unlockResource(inst);
    NyLPC_cStopwatch_finalize(&sw);
    return;
}
Exemplo n.º 26
0
static NyLPC_TBool connect(NyLPC_TiTcpSocket_t* i_inst,const struct NyLPC_TIPv4Addr* i_addr,NyLPC_TUInt16 i_peer_port,NyLPC_TUInt32 i_wait_in_msec)
{
    volatile NyLPC_TUInt8 f;
	NyLPC_TcMiMicIpTcpSocket_t* inst=(NyLPC_TcMiMicIpTcpSocket_t*)i_inst;
    NyLPC_TUInt32 sq;
    NyLPC_TcStopwatch_t sw;
    NyLPC_TUInt16 lport;
    lockResource(inst);
    //ソケットが無効であること。
    if(inst->tcpstateflags!=UIP_CLOSED)
    {
        NyLPC_OnErrorGoto(Error);
    }
    //ポート番号の取得(lockResourceが他のソケットと共有なので、重複ポートの割当は起こりえない。でもちょっと注意して)
    lport=NyLPC_htons(NyLPC_cIPv4_getNewPortNumber(inst->_parent_ipv4));
    if(lport==0){
        NyLPC_OnErrorGoto(Error);
    }
    //connectの為の準備

    //localipとdefault_mmsは別枠で設定
    /* Fill in the necessary fields for the new connection. */
    inst->uip_connr.current_rto32 = UIP_TCP_RTO_CONNECTION_INITIAL;//RTOを短くしてARP発行時の再接続短縮を期待する。
    inst->uip_connr.lport = lport;
    inst->uip_connr.rport = NyLPC_htons(i_peer_port);
    inst->uip_connr.ripaddr=*i_addr;
    inst->uip_connr.snd_nxt32=iss32;//should be random
    /* rcv_nxt should be the seqno from the incoming packet + 1. */
    inst->uip_connr.rcv_nxt32=0;
    //MSSの設定
    inst->uip_connr.peer_mss=inst->uip_connr.default_mss;
    inst->uip_connr.peer_win=1;//periodicの再送信を期待するために相手のWindowサイズは1と仮定する。
    NyLPC_cFifoBuffer_clear(&(inst->rxbuf));
    //ここでステータスがかわる。
    inst->tcpstateflags = UIP_SYN_SENT;
    //前回のデータが残っていた場合の保険
    if(inst->txbuf.rp!=inst->txbuf.wp){
        resetTxQWithUnlock(inst);
    }else{
        unlockResource(inst);
    }

    NyLPC_cStopwatch_initialize(&sw);

    NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
    if(sendWithRetransmit(inst,TCP_SYN,NULL,0,&sw,&sq)==0){
        //ちょっと待つ。
        NyLPC_cThread_yield();
        //キューにあるTXが消えるのを待つ。
        if(waitForTxRemove(inst,sq,&sw)){
            //ACK受信に成功して、TXが消失
            NyLPC_cStopwatch_finalize(&sw);
            return NyLPC_TBool_TRUE;
        }
    }
    //ロックして、強制的なステータス遷移
    lockResource(inst);
    f=inst->tcpstateflags;
    if(f!=UIP_CLOSED){
        //もし、強制CLOSE遷移であれば、RSTも送信。
    	inst->tcpstateflags=UIP_CLOSED;
        unlockResource(inst);
        sendRst(inst);
    }else{
        unlockResource(inst);
    }
    return NyLPC_TBool_FALSE;
Error:
    unlockResource(inst);
    return NyLPC_TBool_FALSE;
}
Exemplo n.º 27
0
/**
 * 再送信処理をセットして、パケットを送信します。
 * この関数は「アンロック状態で」実行してください。
 * @param i_len
 * 送信データサイズを指定します。
 * この番号は、シーケンス番号の加算値ではありませんので、注意をしてください。
 * @return
 * <ul>
 * <li>n=-1:送信キューへの投入に失敗した。</li>
 * <li>n>=0:nバイトのデータを送信キューへの投入することに成功した。</li>
 * </ul>
 * 送信キューに失敗する理由は2つあります。1つは、TXバッファがフルでタイムアウト。もうひとつは、非同期なコネクリョンのリセットです。
 * 失敗した場合、TCPステータスがCLOSEDでなければ、RSTを送信してステータスをCLOSEDにします。
 */
static NyLPC_TInt32 sendWithRetransmit(NyLPC_TcMiMicIpTcpSocket_t* i_inst,NyLPC_TUInt8 i_tcpf,const void* i_buf,NyLPC_TUInt16 i_len,NyLPC_TcStopwatch_t* i_timer,NyLPC_TUInt32* o_ack)
{
    struct NyLPC_TcTcpSocket_TxQItem* txq;
    NyLPC_TUInt16 s;
    void* buf;
    NyLPC_TUInt32 next_ack;
    //送信バッファを取得
    //@bug オブションパケット送信時に4バイト足りないメモリ要求しない?問題になってないけど。
    for(;;){
        buf=NyLPC_cMiMicIpNetIf_allocTxBuf(i_len+(SIZE_OF_IPv4_TCPIP_HEADER),&s);
        if(buf!=NULL){
            break;
        }
        //タイムアウト確認
        if(NyLPC_cStopwatch_isExpired(i_timer)){
            return -1;
        }
    };
    lockResource(i_inst);
    //ペイロードがある場合のみ、相手のwindowサイズが0以上になるのを待つ。
    if(i_len>0){
        while(i_inst->uip_connr.peer_win==0){
            unlockResource(i_inst);
            //時間切れならエラー。
            if(NyLPC_cStopwatch_isExpired(i_timer)){
                return -1;
            }
            NyLPC_cThread_yield();
            lockResource(i_inst);
        }
    }
    //送信キューの取得
    txq=getTxQ(i_inst,i_timer);
    //送信キューが取れなかった。
    if(txq==NULL){
        //シーケンス番号をロールバックできないので、エラーとする。
        unlockResource(i_inst);
        NyLPC_cMiMicIpNetIf_releaseTxBuf(buf);
        return -1;
    }

    //送信バッファを基準とした送信サイズを計算
    s-=SIZE_OF_IPv4_TCPIP_HEADER;
    //送信サイズよりMMSが小さければ、送信サイズを修正
    if(i_inst->uip_connr.peer_mss<s){
        s=i_inst->uip_connr.peer_mss;
    }
    //送信サイズよりpeerのウインドウサイズが小さければ修正
    if(i_inst->uip_connr.peer_win<s){
        s=i_inst->uip_connr.peer_win;
    }
    //送信サイズより、データサイズが小さければ、送信サイズを修正
    if(i_len<s){
        s=i_len;
    }
    //ACK番号の計算
    next_ack=i_inst->uip_connr.snd_nxt32+s+(((i_tcpf&(TCP_FIN|TCP_SYN))!=0x00)?1:0);
    txq->rto32=i_inst->uip_connr.current_rto32;
    txq->tick_of_sent=NyLPC_cStopwatch_now();

    //パケットの書き込み
    setTxPacket(i_inst,buf,i_tcpf,i_buf,s);
    txq->packet=buf;

    //シーケンス番号の更新
    i_inst->uip_connr.snd_nxt32=next_ack;
    //Peerのウインドウサイズを更新
    i_inst->uip_connr.peer_win-=s;
    //ACK番号の返却
    *o_ack=txq->ackno=NyLPC_HTONL(next_ack);
    unlockResource(i_inst);
    NyLPC_cMiMicIpNetIf_sendIPv4Tx(buf);
    return s;
}
Exemplo n.º 28
0
/**
 * See header file.
 */
static void* allocSendBuf(NyLPC_TiTcpSocket_t* i_inst,NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_buf_size,NyLPC_TUInt32 i_wait_in_msec)
{
	NyLPC_TcMiMicIpTcpSocket_t* inst=(NyLPC_TcMiMicIpTcpSocket_t*)i_inst;

    NyLPC_TUInt16 s;
    void* buf;
    NyLPC_TcStopwatch_t sw;

    NyLPC_cStopwatch_initialize(&sw);
    NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);

    //送信バッファを取得
    //@bug バッファが取れるまで通信がブロックするの。ここはなんとかしないと。
    for(;;){
        //ESTABLISHED以外に非同期遷移
        if(inst->tcpstateflags!=UIP_ESTABLISHED){
            NyLPC_cStopwatch_finalize(&sw);
            return NULL;
        }
        buf=NyLPC_cMiMicIpNetIf_allocTxBuf(i_hint+(SIZE_OF_IPv4_TCPIP_HEADER),&s);
        if(buf!=NULL){
            break;
        }
        //タイムアウト時もエラー
        if(NyLPC_cStopwatch_isExpired(&sw)){
            NyLPC_cStopwatch_finalize(&sw);
            return NULL;
        }
    }

//@todo 前段処理と順番を入れ替えて、要求サイズとpeerのwinのうち、小さいほうを割り当てたほうが良くない?
//ここで相手のwin待ちをする理由は、相手に確実に受け取れるサイズを決定する為。
    lockResource(inst);
    //ペイロードがある場合のみ、相手のwindowサイズが0以上になるのを待つ。
    while(inst->uip_connr.peer_win==0){
        unlockResource(inst);
        //ESTABLISHED以外に非同期遷移 orタイムアウト確認
        if(NyLPC_cStopwatch_isExpired(&sw)||(inst->tcpstateflags!=UIP_ESTABLISHED)){
            NyLPC_cMiMicIpNetIf_releaseTxBuf(buf);
            NyLPC_cStopwatch_finalize(&sw);
            return NULL;
        }
        NyLPC_cThread_yield();
        lockResource(inst);
    }
    //送信バッファを基準とした送信サイズを計算
    s-=SIZE_OF_IPv4_TCPIP_HEADER;
    //送信サイズよりMMSが小さければ、送信サイズを修正
    if(inst->uip_connr.peer_mss<s){
        s=inst->uip_connr.peer_mss;
    }
    //送信サイズよりpeerのウインドウサイズが小さければ修正
    if(inst->uip_connr.peer_win<s){
        s=inst->uip_connr.peer_win;
    }
    unlockResource(inst);
    //バッファサイズ確定。
    *o_buf_size=s;
    NyLPC_cStopwatch_finalize(&sw);
    return (NyLPC_TUInt8*)buf+SIZE_OF_IPv4_TCPIP_HEADER;
}
Exemplo n.º 29
0
void* NyLPC_cMiMicIpTcpSocket_parseRx(
	NyLPC_TcMiMicIpTcpSocket_t* i_inst,
    const NyLPC_TcIPv4Payload_t* i_ipp)
{
    int i,s;
    NyLPC_TUInt16 tmp16;
    NyLPC_TUInt16 data_size;
    NyLPC_TUInt8 in_tcpflag=i_ipp->payload.tcp->flags;
    const void* tcp_data_offset;
    NyLPC_TBool is_new_packet;
    int num_of_noack;
    void* dlist[NyLPC_TcTcpSocket_NUMBER_OF_TXQ];
    void* ret;

    //パラメータの計算

    tmp16=NyLPC_TTcpHeader_getHeaderLength(i_ipp->payload.tcp);
    //TCPペイロードの長さは、IPパケットの長さ-(IPヘッダ+TCPヘッダ)
    data_size=NyLPC_TIPv4Header_getPacketLength(i_ipp->header)-NyLPC_TIPv4Header_getHeaderLength(i_ipp->header)-tmp16;
    //TCPデータオフセット
    tcp_data_offset=i_ipp->payload.rawbuf+tmp16;

    //インスタンスをロックする。
    lockResource(i_inst);

    //RSTのチェック。RST受信時は、状態にかかわらず、CLOSEDステータスに移行する。
    if (in_tcpflag & TCP_RST)
    {
        i_inst->tcpstateflags =UIP_CLOSED;
        goto DROP;
    }


    is_new_packet=NyLPC_ntohl(i_ipp->payload.tcp->seqno32)==i_inst->uip_connr.rcv_nxt32;


    //OPTIONの反映

    //MSSの取得
    if(NyLPC_TTcpHeader_getTcpMmsOpt(i_ipp->payload.tcp,&tmp16)){
        //取得で着たら更新
        i_inst->uip_connr.peer_mss=tmp16;
    }
    //受信パケットを元に、未ACKパケットの数を計算
    num_of_noack=getNumOfSending(i_inst,i_ipp->payload.tcp->ackno32);//i_inst->txbuf.num_of_txq;

    //ステータス毎のACK応答
    switch(i_inst->tcpstateflags)
    {
    case UIP_SYN_RCVD:
        //ACKを受信したら、ESTABLISHEDへ。
        //すべてのパケットをACKしたかで判定。()
        if(num_of_noack==0){
            i_inst->tcpstateflags=UIP_ESTABLISHED;
        }else{
            //それ以外のパケットはドロップする。
            break;//goto DROP;
        }
        //新しいパケットがなければ、無応答
        if(!is_new_packet){
            break;//goto DROP;
        }
        //引き続き、ESTABLISHEDの処理へ。
    case UIP_ESTABLISHED:
        if(data_size>0){
            if(is_new_packet){
                if(addRecvData(i_inst,tcp_data_offset,data_size)){
                    //通常のACK返却
                    i_inst->uip_connr.rcv_nxt32+=data_size;
                }else{
                    //失敗したときは必要に応じて単純ACK
                }
            }
        }
        //どちらにしろ、ACK送信
        if(is_new_packet && (in_tcpflag & TCP_FIN)){
            //FINがあるときは、ステータスをCLOSE_WAITへセットして、ACKを返す。
            i_inst->tcpstateflags = UIP_CLOSE_WAIT;
            i_inst->uip_connr.rcv_nxt32++;
        }
        break;
    case UIP_CLOSE_WAIT:
        //必要に応じたACK応答
        break;
    case UIP_LAST_ACK:
        //ACK(by FIN)が得られたなら、CLOSEDへ。
        if(num_of_noack==0){
            i_inst->tcpstateflags=UIP_CLOSED;
        }
        //必要に応じたACK応答
        break;
    case UIP_FIN_WAIT_1:
        //FIN受信->CLOSINGへ
        if(is_new_packet){
            i_inst->uip_connr.rcv_nxt32+=data_size;
            if(in_tcpflag & TCP_FIN){
                i_inst->uip_connr.rcv_nxt32++;
                if(num_of_noack==0){
                    //FINとACKを受信
                    i_inst->tcpstateflags=UIP_TIME_WAIT;
                }else{
                    //FINのみ
                    i_inst->tcpstateflags=UIP_CLOSING;
                }
            }
        }else if(num_of_noack==0){
            //ACKのみ
            i_inst->tcpstateflags=UIP_FIN_WAIT_2;
        }
        //必要に応じたACK応答
        break;
    case UIP_FIN_WAIT_2:
        //FIN受信->TIME_WAITへ(pureACK)
        if(is_new_packet && (in_tcpflag & TCP_FIN)){
            i_inst->uip_connr.rcv_nxt32++;
            i_inst->tcpstateflags=UIP_TIME_WAIT;
        }
        break;
    case UIP_CLOSING:
        //ACK受信したら、TIME_WAITへ
        if(num_of_noack==0){
            i_inst->tcpstateflags=UIP_TIME_WAIT;
        }
        break;
    case UIP_CLOSED:
        //何もできない。何もしない。
        break;
    case UIP_TIME_WAIT:
        //最終ACKを送り続ける。
        break;
    case UIP_SYN_SENT:
        //connect関数実行中しか起動しないステータス
        if(num_of_noack==0){
            i_inst->tcpstateflags=UIP_ESTABLISHED;
            i_inst->uip_connr.rcv_nxt32=NyLPC_ntohl(i_ipp->payload.tcp->seqno32)+1;
        }else{
            //それ以外のパケットはドロップする。
            break;//goto DROP;
        }
        //ACKを送る。
        break;
    default:
        goto DROP;
    }
    //ウインドウサイズを更新
    i_inst->uip_connr.peer_win=NyLPC_ntohs(i_ipp->payload.tcp->wnd16);

    //送信キューから、Peerが受信したデータを削除する。
    if(in_tcpflag & TCP_ACK){
        //再送パケットキューから送信済みのデータを回収(後で開放)
        NyLPC_Trace();
        s=updateTxQByIndex(i_inst,i_ipp->payload.tcp->ackno32,dlist);
        NyLPC_Trace();
    }else{
        s=0;
    }
    //新しいパケットがきた場合は、再送キューのACKを更新する。
    if(is_new_packet){
        //再送キューのACKを更新
        updateTxAck(i_inst,NyLPC_htonl(i_inst->uip_connr.rcv_nxt32));
    }

    //送信キューのない
    if(((in_tcpflag&(TCP_FIN|TCP_SYN))!=0x00) ||
        ((!is_new_packet) && (data_size>0)))
    {
        //ソケットからPureACKを生成 as setPacket(i_inst,i_ipp,TCP_ACK,NULL,0);
        ret=NyLPC_cMiMicIpNetIf_allocSysTxBuf();
        setTxPacket(i_inst,ret,TCP_ACK,NULL,0);
    }else{
        ret=NULL;
    }
    unlockResource(i_inst);
    //取り外したTXメモリの開放
    for(i=0;i<s;i++){
        //取り外したTXメモリを開放
        NyLPC_cMiMicIpNetIf_releaseTxBuf(dlist[i]);
    }
NyLPC_Trace();
    return ret;
DROP:
    //ACKしたパケットを送信キューから削除
    unlockResource(i_inst);
NyLPC_Trace();
    return NULL;
}