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; }
/** * 受信バッファをシークします。 * シーク後に、遅延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); }
/** * 空きキューを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; }
/** * 事前に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; }
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); }
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); }
/** * 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; }
/** * 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; }
/** * 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; }
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; }
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; }
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; }
/** * この関数は、ソケットの受信バッファの読み取り位置と、読み出せるデータサイズを返却します。 * 関数はポインターを返却するだけで、バッファの読み取り位置をシークしません。 * シークするには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; }
/** * \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); }
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); }
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; }
/** * 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; }
/** * この関数は、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; }
/** * 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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
/** * 再送信処理をセットして、パケットを送信します。 * この関数は「アンロック状態で」実行してください。 * @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; }
/** * 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; }
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; }