def render(self, resrc): """ Ask a resource to render itself. @param resrc: a L{twisted.web.resource.IResource}. """ try: body = resrc.render(self) except UnsupportedMethod, e: sAllowedMethodList = e.allowedMethods if (self.method == "HEAD") and ("GET" in sAllowedMethodList): # We must support HEAD (RFC 2616, 5.1.1). If the # resource doesn't, fake it by giving the resource # a 'GET' request and then return only the headers, # not the body. log.Info("Using GET to fake a HEAD request for %s" % resrc) self.method = "GET" #来自http.Request self._inFakeHead = True #来自web.server.Request body = resrc.render(self) if body is NOT_DONE_YET: log.Info("Tried to fake a HEAD request for %s, but it got away from me." % resrc) # Oh well, I guess we won't include the content length. else: self.setHeader("content-length", str(len(body))) self._inFakeHead = False self.method = "HEAD" self.write("") self.finish() return if self.method in SUPPORT_METHOD_LIST: # We MUST include an Allow header # (RFC 2616, 10.4.6 and 14.7) self.setHeader('Allow', ', '.join(sAllowedMethodList)) s = ("""Your browser approached me (at %(URI)s) with""" """ the method "%(method)s". I only allow""" """ the method%(plural)s %(allowed)s here.""" % { "URI" : escape(self.uri), "method" : self.method, "plural" : ((len(sAllowedMethodList) > 1) and "s") or "", "allowed" : string.join(sAllowedMethodList, ", ") }) epage = resource.ErrorPage(http.NOT_ALLOWED, "Method Not Allowed", s) body = epage.render(self) else: epage = resource.ErrorPage( http.NOT_IMPLEMENTED, "Huh?", "I don't know how to treat a %s request." % (escape(self.method),)) body = epage.render(self)
def RemoveClient(self, sName): if not sName in self.m_ClientDict: return log.Info("remove rpc_client %s" % sName) oClient = self.m_ClientDict[sName] del self.m_ClientDict[sName] self.OnClientLostConnect(sName, oClient)
def remote_AddClient(self, sName, oClient): log.Info("add rpc_client(%s)" % sName) oOld = self.m_ClientDict.get(sName, None) if oOld: self.RemoveClient(sName) self.m_ClientDict[sName] = oClient self.OnClientConnect(sName, oClient)
def connectionMade(self): """建立连接后的处理""" log.Info("Client %d login at [%s,%d]" % (self.transport.sessionno + CONN_ID_MIN, self.transport.client[0], self.transport.client[1])) self.factory.ConnectionMade(self) self.m_DataHandler = self.DataHandleCoroutine() self.m_DataHandler.next()
def ConnectServerSuccess(oRemote, sName): """连接服务器成功""" oClient = g_ClientDict.get(sName, None) if not oClient: return log.Info("%s(rpc) connect to RpcServer_%s%s success" % (sName, oClient.m_Server, oClient.m_Address)) oRemote.callRemote("AddClient", oClient.m_Name, oClient.m_Local)
def CallServerResult(result, bSuccess, sName, key, *args, **kw): """服务端反馈,将反馈转发给sName客户端""" oClient = g_ClientDict.get(sName, None) if not oClient: return if not bSuccess: log.Info("CallFailed(%s, %s):%s" % (sName, key, result)) return oClient.CallResult(key, result, *args, **kw)
def Start(self): if self.m_State == SERVER_STATE_NONE: log.Fatal("server need init first") return elif self.m_State == SERVER_STATE_START: log.Fatal("server(%s) already started" % self.m_Name) return log.Info("Server(%s) start now" % self.m_Name) reactor.callLater(1, self.ServerStart) reactor.run()
def Stop(self): if self.m_State != SERVER_STATE_START: log.Fatal("server(%s) has not started, cannot stop!" % self.m_Name) return self.m_State = SERVER_STATE_STOP log.Info("server(%s) stopped!" % self.m_Name) cbFunc = self.m_Handler.get("ServerStop", None) if cbFunc: cbFunc(self) reactor.stop()
def Connect(self): """ 连接到RPC服务器 @return: """ reactor.connectTCP(self.m_Address[0], self.m_Address[1], self.m_Factory) log.Info("%s(rpc) try connect to %s%s" % (self.m_Name, self.m_Server, self.m_Address)) #向RPC服务器注册自己的服务列表,方便服务器调用 oDefer = self.m_Factory.getRootObject() oDefer.addCallback(ConnectServerSuccess, self.m_Server) oDefer.addErrback(ConnectServerFailed, self.m_Server)
def LoadConfigByPath(self, sRoot): """ 加载指定目录下的资源文件到内存中 @dData,dict,资源的存储地址 @sRoot,string,当前需要访问的目录 """ dData = {} for sPath in os.listdir(sRoot): sFull = os.path.join(sRoot, sPath) if os.path.isfile(sFull): sName, sExt = os.path.splitext(sPath) if not self.ValidFile(sExt): continue dData[sName] = self.LoadFile(sFull) log.Info("[CC] load : %s -> %s" % (sName, sFull)) elif os.path.isdir(sFull) and self.ValidDir(sPath): dData[sPath] = self.LoadConfigByPath(sFull) return dData
def DataHandleCoroutine(self): iConnID = self.GetConnID() #获取协议头的长度 while True: data = yield self.m_Buff += data while self.m_Buff.__len__() >= packet.PACKET_HEAD_LEN: PackInfo = packet.UnpackNet(iConnID, self.m_Buff) if not PackInfo: log.Fatal("illegal data package -- [%s]" % PackInfo) self.transport.loseConnection() break sProtoName, iPackLen, dProtoData = PackInfo self.m_Buff = self.m_Buff[packet.PACKET_HEAD_LEN + iPackLen:] log.Info("recv %s/%d from %d" % (sProtoName, iPackLen, iConnID)) self.factory.DataReceived(self.GetConnID(), sProtoName, dProtoData)
def InitConfig(self, dConfig): """ 初始化配置管理中心,务必在配置管理中心实例化后优先调用 @dConfig,dict,配置字典 """ if self.m_Init: raise "CC.InitConfig should be called first" self.m_Type = dConfig.get("type", RES_TYPE_PATH) self.m_Path = dConfig.get("path", "./") if self.m_Type == RES_TYPE_PATH: if not os.path.exists(self.m_Path) or not os.path.isdir( self.m_Path): raise "[CC] path(%s) not existed" % self.m_Path elif self.m_Type == RES_TYPE_PAK: if not os.path.exists(self.m_Path) or not os.path.isfile( self.m_Path): raise "[CC] file(%s) not existed" % self.m_Path else: raise "[CC]Error ResType(%d)" % self.m_Type self.m_Crypt = dConfig.get("crypt", False) self.m_IncludeExt = dConfig.get("include_ext", ".json").split(",") sValue = dConfig.get("exclude_ext", "") if sValue: self.m_ExcludeExt = sValue.split(",") sValue = dConfig.get("include_dir", "") if sValue: self.m_IncludeDir = sValue.split(",") sValue = dConfig.get("exclude_dir", "") if sValue: self.m_ExcludeDir = sValue.split(",") if self.m_Type == RES_TYPE_PATH: self.m_Data = self.LoadConfigByPath(self.m_Path) elif self.m_Type == RES_TYPE_PAK: self.m_Data = self.LoadConfigByPak() self.m_Init = True log.Info("[CC] init success!")
def clientConnectionLost(self, connector, reason, reconnecting=0): pb.PBClientFactory.clientConnectionLost(self, connector, reason, reconnecting) log.Info(u"和RPC[%s]的链接断开了,尝试重连...", self.m_Name) ReConnectServer(self.m_Name)
def ConnectServerFailed(error, sName): log.Info("connect failed, %s" % error.getErrorMessage()) reactor.callLater(1, ReConnectServer, sName)
def connectionLost(self, reason=protocol.connectionDone): iConnID = self.GetConnID() log.Info("Client %d logout" % iConnID) self.factory.ConnectionLost(iConnID)
class CDelayRequest(Request): def __init__(self, *args, **kw): Request.__init__(self, *args, **kw) #渲染,继承自Request def render(self, resrc): """ Ask a resource to render itself. @param resrc: a L{twisted.web.resource.IResource}. """ try: body = resrc.render(self) except UnsupportedMethod, e: sAllowedMethodList = e.allowedMethods if (self.method == "HEAD") and ("GET" in sAllowedMethodList): # We must support HEAD (RFC 2616, 5.1.1). If the # resource doesn't, fake it by giving the resource # a 'GET' request and then return only the headers, # not the body. log.Info("Using GET to fake a HEAD request for %s" % resrc) self.method = "GET" #来自http.Request self._inFakeHead = True #来自web.server.Request body = resrc.render(self) if body is NOT_DONE_YET: log.Info("Tried to fake a HEAD request for %s, but it got away from me." % resrc) # Oh well, I guess we won't include the content length. else: self.setHeader("content-length", str(len(body))) self._inFakeHead = False self.method = "HEAD" self.write("") self.finish() return if self.method in SUPPORT_METHOD_LIST: # We MUST include an Allow header # (RFC 2616, 10.4.6 and 14.7) self.setHeader('Allow', ', '.join(sAllowedMethodList)) s = ("""Your browser approached me (at %(URI)s) with""" """ the method "%(method)s". I only allow""" """ the method%(plural)s %(allowed)s here.""" % { "URI" : escape(self.uri), "method" : self.method, "plural" : ((len(sAllowedMethodList) > 1) and "s") or "", "allowed" : string.join(sAllowedMethodList, ", ") }) epage = resource.ErrorPage(http.NOT_ALLOWED, "Method Not Allowed", s) body = epage.render(self) else: epage = resource.ErrorPage( http.NOT_IMPLEMENTED, "Huh?", "I don't know how to treat a %s request." % (escape(self.method),)) body = epage.render(self) # end except UnsupportedMethod if body == NOT_DONE_YET: return if not isinstance(body, defer.Deferred) and type(body) is not types.StringType: body = resource.ErrorPage( http.INTERNAL_SERVER_ERROR, "Request did not return a string", "Request: " + html.PRE(reflect.safe_repr(self)) + "<br />" + "Resource: " + html.PRE(reflect.safe_repr(resrc)) + "<br />" + "Value: " + html.PRE(reflect.safe_repr(body))).render(self) if self.method == "HEAD": if len(body) > 0: # This is a Bad Thing (RFC 2616, 9.4) log.Info("Warning: HEAD request %s for resource %s is" " returning a message body." " I think I'll eat it." % (self, resrc)) self.setHeader("content-length", str(len(body))) self.write("") self.finish() else: if isinstance(body, defer.Deferred): body.addCallback(self.DeferWrite) else: self.setHeader("content-length", str(len(body))) self.write(body) self.finish()
def InitConfig(self, sName, dConfig): if "name" in dConfig: sName = dConfig["name"] self.m_Name = sName #服务器配置 self.m_bFrontEnd = dConfig.get("frontend", False) #执行根目录 sPath = dConfig.get("path", None) if sPath: import os, sys os.chdir(sPath) sys.path.insert(0, sPath) log.Info("server(%s) change root path to (%s)" % (self.m_Name, sPath)) #日志路径 self.m_LogPath = dConfig.get("log", "./") log.InitLog(self.m_LogPath) #初始化net,目前仅有前端服务器支持net参数 if self.m_bFrontEnd: dNetCfg = dConfig.get("net", None) if not dNetCfg: log.Fatal("server(%s) need config about network" % self.m_Name) return sNetType = dNetCfg["type"].lower() if sNetType == NET_TYPE_TCP: import wafer.tcp self.m_NetType = NET_TYPE_TCP self.m_Modules["net"] = wafer.tcp.CreateServer( self.m_Name, dNetCfg["host"], dNetCfg["port"]) log.Info("%s(%s) listen at %d" % (self.m_Name, sNetType, dNetCfg["port"])) elif sNetType == NET_TYPE_HTTP: self.m_NetType = NET_TYPE_HTTP elif sNetType == NET_TYPE_WEBSOCKET: self.m_NetType = NET_TYPE_WEBSOCKET #初始化web dWebCfg = dConfig.get("web", None) if dWebCfg: import wafer.web sHost = dWebCfg.get("url", "127.0.0.1") self.m_Modules["web"] = wafer.web.CreateWebServer( sHost, dWebCfg["port"]) log.Info("server(%s) listen web port at %s:%d" % (self.m_Name, sHost, dWebCfg["port"])) #RPC初始化 dRpcList = dConfig.get("rpc", []) if dRpcList: import wafer.rpc for dRpcCfg in dRpcList: sRpcName = dRpcCfg["name"] if dRpcCfg.get("server", False): oRpcNode = wafer.rpc.CreateRpcServer( sRpcName, dRpcCfg["port"]) log.Info("%s(rpc) listen at %d" % (sRpcName, dRpcCfg["port"])) else: tAddress = (dRpcCfg["host"], dRpcCfg["port"]) oRpcNode = wafer.rpc.CreateRpcClient( self.m_Name, sRpcName, tAddress) log.Info("%s create rpc_client to %s" % (self.m_Name, sRpcName)) self.m_RpcDict[sRpcName] = oRpcNode #redis dCfg = dConfig.get("redis", None) if dCfg: import redis self.m_Modules["redis"] = redis.Redis( host=dCfg.get("host", "localhost"), port=dCfg.get("port", 6379), db=dCfg.get("db", 0), ) log.Info("server(%s) start redis" % self.m_Name) #每个进程配置init选项,启动时将加载此文件 sInitFile = dConfig.get("init", None) mod = self.Import(sInitFile) if hasattr(mod, "ServerStart"): self.m_Handler["ServerStart"] = mod.ServerStart if hasattr(mod, "ServerStop"): self.m_Handler["ServerStop"] = mod.ServerStop if self.m_NetType == NET_TYPE_TCP: oNetNode = self.m_Modules.get("net", None) if oNetNode: if hasattr(mod, "ConnectionLost"): oNetNode.GetService().SetCallback("__OnConnectionLost", mod.ConnectionLost) if hasattr(mod, "ConnectionMade"): oNetNode.GetService().SetCallback("__OnConnectionMade", mod.ConnectionMade) self.m_State = SERVER_STATE_INIT log.Info("server(%s) init success!" % self.m_Name)