/* socket = network.socket(type) */ static int net_socket (lua_State *L) { static const char *const types[] = {"listen", "connection", "datagram", NULL}; loski_NetDriver *drv = (loski_NetDriver *)lua_touserdata(L, lua_upvalueindex(1)); int type = luaL_checkoption(L, 1, NULL, types); LuaSocket *ls = newsock(L, type); int res = loski_createsocket(drv, &ls->socket, type); if (res == 0) ls->closed = 0; return pushsockres(L, 1, res); }
/* 何番のバーチャルポートで待つのかを指定するサーバー用。 */ int usocket_serv(int index ) { CHECKFDNUM(index); if( ! stb[index].use ){ bzero( &stb[index] , sizeof( stb[0] ) ); newsock( index ); return index; } else { udptcp.errno = EALREADYUSE; return -1; } }
/* socket表へのインデクスをかえす return values: >= 0 OK < 0 Error */ int usocket( void ) { int i; for(i=0;i<MAXCON;i++){ if( ! stb[i].use ){ bzero( &stb[i] , sizeof( stb[0] ) ); newsock( i ); return i; } } udptcp.errno = ENOMORESOCKET; /* too many open file */ return -1; }
/* socket [, errmsg] = socket:accept([getfrom]) */ static int lst_accept (lua_State *L) { loski_NetDriver *drv = (loski_NetDriver *)lua_touserdata(L, lua_upvalueindex(1)); loski_Socket *socket = tosock(L, LOSKI_LSTNSOCKET); LuaSocket *ls = newsock(L, LOSKI_CONNSOCKET); int res, nr = 1; if (lua_toboolean(L, 2)) { loski_Address address; res = loski_acceptsocket(drv, socket, &ls->socket, &address); if (res == 0) nr += pushaddress(drv, L, &address); } else { res = loski_acceptsocket(drv, socket, &ls->socket, NULL); } if (res == 0) ls->closed = 0; return pushsockres(L, nr, res); }
/* rest service entry point */ INT32 pmdRestSvcEntryPoint ( pmdEDUCB *cb, void *pData ) { INT32 rc = SDB_OK ; pmdKRCB *krcb = pmdGetKRCB() ; monDBCB *mondbcb = krcb->getMonDBCB () ; pmdEDUMgr *eduMgr = cb->getEDUMgr() ; ossSocket *pListerner = ( ossSocket* )pData ; EDUID agentEDU = PMD_INVALID_EDUID ; if ( SDB_OK != ( rc = eduMgr->activateEDU ( cb )) ) { goto error ; } while ( !cb->isDisconnected() ) { SOCKET s ; rc = pListerner->accept ( &s, NULL, NULL ) ; if ( SDB_TIMEOUT == rc || SDB_TOO_MANY_OPEN_FD == rc ) { rc = SDB_OK ; continue ; } if ( rc && PMD_IS_DB_DOWN ) { rc = SDB_OK ; goto done ; } else if ( rc ) { PD_LOG ( PDERROR, "Failed to accept rest socket, rc: %d", rc ) ; if ( pListerner->isClosed() ) { break ; } else { continue ; } } cb->incEventCount() ; ++mondbcb->numConnects ; void *pData = NULL ; *((SOCKET *) &pData) = s ; if ( !krcb->isActive() ) { ossSocket newsock ( &s ) ; newsock.close () ; continue ; } if ( SDB_ROLE_OM == pmdGetDBRole() || SDB_ROLE_DATA == pmdGetDBRole() || SDB_ROLE_STANDALONE == pmdGetDBRole() || SDB_ROLE_COORD == pmdGetDBRole() ) { rc = eduMgr->startEDU ( EDU_TYPE_RESTAGENT, pData, &agentEDU ) ; } else { rc = eduMgr->startEDU ( EDU_TYPE_HTTPAGENT, pData, &agentEDU ) ; } if ( rc ) { PD_LOG( ( rc == SDB_QUIESCED ? PDWARNING : PDERROR ), "Failed to start edu, rc: %d", rc ) ; ossSocket newsock ( &s ) ; newsock.close () ; continue ; } } //while ( ! cb->isDisconnected() ) done : return rc ; error : goto done ; }
/* rest service entry point */ INT32 pmdRestSvcEntryPoint ( pmdEDUCB *cb, void *pData ) { INT32 rc = SDB_OK ; pmdKRCB *krcb = pmdGetKRCB() ; pmdOptionsCB *optionCB = krcb->getOptionCB() ; monDBCB *mondbcb = krcb->getMonDBCB () ; pmdEDUMgr *eduMgr = cb->getEDUMgr() ; ossSocket *pListerner = ( ossSocket* )pData ; EDUID agentEDU = PMD_INVALID_EDUID ; if ( SDB_OK != ( rc = eduMgr->activateEDU ( cb )) ) { goto error ; } while ( !cb->isDisconnected() && !pListerner->isClosed() ) { SOCKET s ; rc = pListerner->accept ( &s, NULL, NULL ) ; if ( SDB_TIMEOUT == rc ) { rc = SDB_OK ; continue ; } else if ( SDB_TOO_MANY_OPEN_FD == rc ) { pListerner->close() ; PD_LOG( PDERROR, "Can not accept more connections because of " "open files upto limits, restart listening" ) ; pmdIncErrNum( rc ) ; while( !cb->isDisconnected() ) { pListerner->close() ; ossSleep( 2 * OSS_ONE_SEC ) ; rc = pListerner->initSocket() ; if ( rc ) { continue ; } rc = pListerner->bind_listen() ; if ( rc ) { continue ; } PD_LOG( PDEVENT, "Restart listening on port[%d] succeed", pListerner->getLocalPort() ) ; break ; } continue ; } if ( rc && PMD_IS_DB_DOWN() ) { rc = SDB_OK ; goto done ; } else if ( rc ) { PD_LOG ( PDERROR, "Failed to accept rest socket, rc: %d", rc ) ; if ( pListerner->isClosed() ) { break ; } else { continue ; } } cb->incEventCount() ; void *pData = NULL ; *((SOCKET *) &pData) = s ; if ( !krcb->isActive() ) { ossSocket newsock ( &s ) ; newsock.close () ; continue ; } mondbcb->connInc(); if ( mondbcb->isConnLimited( optionCB->getMaxConn() ) ) { ossSocket newsock ( &s ) ; newsock.close () ; mondbcb->connDec(); continue ; } rc = eduMgr->startEDU ( EDU_TYPE_RESTAGENT, pData, &agentEDU ) ; if ( rc ) { PD_LOG( ( rc == SDB_QUIESCED ? PDWARNING : PDERROR ), "Failed to start edu, rc: %d", rc ) ; ossSocket newsock ( &s ) ; newsock.close () ; mondbcb->connDec(); continue ; } } //while ( ! cb->isDisconnected() ) done : return rc ; error : goto done ; }
INT32 pmdFapListenerEntryPoint ( pmdEDUCB *cb, void *pData ) { INT32 rc = SDB_OK ; PD_TRACE_ENTRY ( SDB_PMDTCPLSTNENTPNT ) ; pmdKRCB *krcb = pmdGetKRCB() ; monDBCB *mondbcb = krcb->getMonDBCB () ; pmdEDUMgr * eduMgr = cb->getEDUMgr() ; EDUID agentEDU = PMD_INVALID_EDUID ; pmdEDUParam *param = ( pmdEDUParam * )pData ; ossSocket *pListerner = (ossSocket *)(param->pSocket) ; IPmdAccessProtocol *protocol = param->protocol ; SDB_OSS_DEL param ; param = NULL ; if ( SDB_OK != ( rc = eduMgr->activateEDU ( cb ) ) ) { goto error ; } while ( ! cb->isDisconnected() ) { SOCKET s ; rc = pListerner->accept ( &s, NULL, NULL ) ; if ( SDB_TIMEOUT == rc || SDB_TOO_MANY_OPEN_FD == rc ) { rc = SDB_OK ; continue ; } if ( rc && PMD_IS_DB_DOWN ) { rc = SDB_OK ; goto done ; } else if ( rc ) { PD_LOG ( PDERROR, "Failed to accept socket in TcpListener(rc=%d)", rc ) ; if ( pListerner->isClosed() ) { break ; } else { continue ; } } cb->incEventCount() ; ++mondbcb->numConnects ; pmdEDUParam *pParam = SDB_OSS_NEW pmdEDUParam() ; *(( SOCKET *)&pParam->pSocket) = s ; pParam->protocol = protocol ; if ( !krcb->isActive() ) { ossSocket newsock ( &s ) ; newsock.close () ; SDB_OSS_DEL pParam ; pParam = NULL ; continue ; } rc = eduMgr->startEDU ( EDU_TYPE_FAPAGENT, (void *)pParam, &agentEDU ) ; if ( rc ) { PD_LOG( ( rc == SDB_QUIESCED ? PDWARNING : PDERROR ), "Failed to start edu, rc: %d", rc ) ; ossSocket newsock ( &s ) ; newsock.close () ; SDB_OSS_DEL pParam ; pParam = NULL ; continue ; } } //while ( ! cb->isDisconnected() ) if ( SDB_OK != ( rc = eduMgr->waitEDU ( cb ) ) ) { goto error ; } done : PD_TRACE_EXITRC ( SDB_PMDTCPLSTNENTPNT, rc ); return rc; error : switch ( rc ) { case SDB_SYS : PD_LOG ( PDSEVERE, "System error occured" ) ; break ; default : PD_LOG ( PDSEVERE, "Internal error" ) ; break ; } goto done ; }
/* 頻繁に呼びだされる、I/Oする関数。パケットの内容を見て、 return values: いくつのパケットを受信したか。 */ int uproc(void) { fd_set rfd , wfd; int a; int rcount =0; int i; int read_ok ; int write_more; while(1){ struct timeval tm; tm.tv_sec = 0; tm.tv_usec = 0; FD_ZERO( &rfd ); FD_ZERO( &wfd ); FD_SET( udptcp.mainsockfd , &rfd); FD_SET( udptcp.mainsockfd , &wfd ); a = select( 100 , &rfd , &wfd , (fd_set*)0 , &tm ); read_ok = 0; write_more = 0; /* 書きこみ可能 */ if( FD_ISSET( udptcp.mainsockfd , &wfd )){ int i,sr; unsigned long start,end,datalen; char buf[SEGMENTSIZ+HEADERSIZE]; for(i=0;i<MAXCON;i++){ /* start からendまで書きこみたい。長さは適切になってい */ /* る。 */ if( stb[i].use == 0 ) continue; getwfdpart( i , &start, &end ,SEGMENTSIZ ); datalen = end-start; if( datalen >0 ){ fprintf( stderr, "send_start:%d len:%d\n" , start,datalen ); makeheader( buf , start , ACK_NOUSE , 0 , 0 , 0 , 0 , datalen ); bcopy( stb[i].wb+start ,buf + HEADERSIZE , datalen); /* 送信 */ sr = sender( buf , datalen +HEADERSIZE , stb[i].addr_dest ); if( sr != ( datalen+HEADERSIZE) ){ break; } else { /* ちゃんと送れたからバッファを更新 */ setsend( i, start , end ); } } } write_more = 0; /* 今はいつでもwrite_more = 0 PENDING */ } /* 読みこみ可能 */ if( FD_ISSET( udptcp.mainsockfd , &rfd )){ int n; char buf[SEGMENTSIZ+HEADERSIZE]; struct sockaddr_in sin; int clilen; read_ok = 1; n = recvfrom( udptcp.mainsockfd , buf , sizeof( buf ) , 0 , (struct sockaddr*)&sin , &clilen); if( n< 0 ) continue; fprintf( stderr , "recvfrom addr:%x\n", sin.sin_addr.s_addr ); if( n > 0 ){ /* パケットを読みこむことができた。 ackフィールドにデータがある場合はackの処理をする。 データが0xffffffffの場合はデータである。*/ int index; unsigned long seq , ack; unsigned char rst,syn,fin,ref; unsigned long length; getheader( buf , &seq , &ack , &rst , &syn , &fin , &ref ,&length ); /* 対応するindexをポートの情報から得る。ないときは */ /* accept待ち行列に追加する。 */ index = getindexbyaddr( sin.sin_addr.s_addr ); if( syn ){ /* SYNである。 */ if( index == -1 ){ fprintf( stderr, "SYN!\n"); /* 今までにないアドレスだ(サーバーにとっては当然)。 accept待ちソケットをついか */ for(i=3;i<MAXCON;i++){ if( stb[i].use == 0 ){ bzero( &stb[i] , sizeof( stb[0] ) ); newsock(i); stb[i].acceptwait = 1; stb[i].read_syn = 1; /* synがきたから */ stb[i].addr_dest = sin.sin_addr.s_addr; break; } } if( i == MAXCON ){ /* これ以上何もできないからパケットを捨てる。 クライアントからはサーバーが応答しないように見える から、タイムアウトすることだろう。*/ } else { /* SYNをかえす */ makeheader( buf , 0 , 0, 0 , 1 , 0, 0 ,0 );/*ACK->0*/ sender( buf , HEADERSIZE , sin.sin_addr.s_addr ); } } else { /* 今までに存在していたソケットにSYNがきたら、 */ /* それはクライアントでは当然である */ if( ack == ACK_NOUSE ){ /* ACK_NOUSEはデータ送信のときにつかうのでSYNは2回こない. そんな誤ったデータはすてる*/ fprintf( stderr , "Bad SYN code\n"); } else { /* SYNのACKであるからsenderしない */ stb[index].read_syn = 1; fprintf( stderr , "fd%d read_syn on!\n",index ); } } } else if( ack == ACK_NOUSE ){ /* データである。*/ int i; if( index == -1 ){ /* 存在しないソケットにたいしてデータがくることはない。 */ fprintf( stderr, "Bad Data\n" ); } else { /* すでに確立しているコネクションのためのデータだから、readbufにくわえる。 */ int ret = addrb( index , buf + HEADERSIZE ,seq , length ); if( ret == 0 ){ /* 読みこみ成功したからACKかえす。 長さもそのまま返す。*/ makeheader( buf , 0xffffffff , seq , 0 , 0, 0 ,0 ,length ); sender( buf , HEADERSIZE , sin.sin_addr.s_addr ); } else { /* 失敗したからACKかえさない(再送させんと) */ } } } else { /* ACKである. */ /* ACKをうけとったら、 ACKの値をもつwritebufがあるか検索 */ if( index == -1 ){ /* 存在しないソケットにACKきても意味なし。無視する */ fprintf( stderr , "Bad ack code %\n" ); } else{ /* そのまま返ってきた長さがここに生かされる。 ACKパケットの場合だけ、length分のデータをもたない */ setack( index , ack, length ); } } } rcount ++; fprintf( stderr, "R "); } /* もう読みこむものがなくなって、書きこむものもなくなったら返す */ if( read_ok == 0 && write_more == 0 ){ /* fprintf( stderr , "%d %d\n" , read_ok , write_more );*/ break; } } return rcount; }