/**
* Copyright 2013, Landz and its contributors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package z.net;
import z.util.Unsafes;
import static z.znr.socket.SocketOptions.setOptReuseAddr;
import static z.znr.socket.SocketOptions.setOptTcpNoDelay;
import static z.znr.socket.Sockets.*;
import static z.znr.Errno.*;
/**
*/
public class NetModule {
public static final int MAX_SUPPORTED_SOCKS =
Integer.getInteger("z.net.maxSupportedSocks",128*1024);
// private static final int INITIAL_SUPPORTED_SOCKS =
// Integer.getInteger("z.net.initialSupportedSocks", 64*1024);
private final AsyncIOThreadPool asyncIOPool;
public NetModule(AsyncIOThreadPool asyncIOPool) {
this.asyncIOPool = asyncIOPool;
}
public final void startServer(String ipAddress, int port) {
asyncIOPool.start();
int serverfd = socketTcp();
contract(serverfd);
//FIXME: works for inheritable options
setOptReuseAddr(serverfd, true);
setOptTcpNoDelay(serverfd, true);
//TODO: TCP_KEEPALIVE
//TODO: TCP_FASTOPEN and others...
int suc = bind(serverfd, ipAddress, port);
contract(suc);
suc = listen(serverfd);
contract(suc);
Thread acceptor = new Acceptor(serverfd);
acceptor.start();
}
private final class Acceptor extends Thread {
private final int serverfd;
private int robinIndex;
public Acceptor(int serverfd) {
setName("z.net Acceptor");
setDaemon(true);
this.serverfd = serverfd;
}
@Override
public void run() {
int cfd;
for (;;) {
cfd=acceptNonBlock(serverfd);
if (cfd>0) {
if (robinIndex == asyncIOPool.poolSize)
robinIndex = 0;
asyncIOPool.accept(cfd, robinIndex++);
} else {
if (cfd==(-EAGAIN)) {
Unsafes.UNSAFE.park(false,500L);//TODO: accepting rate control
}else {
return;
}
}
}
}
}
//======================================================================
//common contracts
protected static boolean enable_contracts = true;
private static final void contract(int num) {
if (enable_contracts) {
if (num >= 0) {
return;
} else {
new RuntimeException("Meeting error:"+ getErrnoString(-num));
}
}
}
}