/*============================================================================= WebServer is responsible for listening to requests on the selected http port and will guide requests to the correct application. =============================================================================*/ class WebServer extends TcpLink; var config string ServerName; var config string Applications[10]; var config string ApplicationPaths[10]; var config bool bEnabled; var config int ListenPort; var config int MaxConnections; var config int DefaultApplication; var config int ExpirationSeconds; // How long images can be cached .. default is 24 hours var string ServerURL; var WebApplication ApplicationObjects[10]; var int ConnectionCount; // MC: Debug // var int ConnId; function BeginPlay() { local int i; local class ApplicationClass; local IpAddr l; local string s; // Destroy if not a server if (Level.NetMode == NM_StandAlone || Level.NetMode == NM_Client) { Destroy(); return; } if(!bEnabled) { Log("Webserver is not enabled. Set bEnabled to True in Advanced Options."); Destroy(); return; } Super.BeginPlay(); for(i=0;i<10;i++) { if(Applications[i] == "") break; ApplicationClass = class(DynamicLoadObject(Applications[i], class'Class')); if(ApplicationClass != None) { ApplicationObjects[i] = New(None) ApplicationClass; ApplicationObjects[i].Level = Level; ApplicationObjects[i].WebServer = Self; ApplicationObjects[i].Path = ApplicationPaths[i]; ApplicationObjects[i].Init(); } } if(ServerName == "") { GetLocalIP(l); s = IpAddrToString(l); i = InStr(s, ":"); if(i != -1) s = Left(s, i); ServerURL = "http://"$s; } else ServerURL = "http://"$ServerName; if(ListenPort != 80) ServerURL = ServerURL $ ":"$string(ListenPort); BindPort( ListenPort ); Listen(); } event Destroyed() { local int i; for(i = 0; i < ArrayCount(ApplicationObjects); i++) if (ApplicationObjects[i] != None) ApplicationObjects[i].CleanupApp(); Super.Destroyed(); } event GainedChild( Actor C ) { Super.GainedChild(C); ConnectionCount++; // if too many connections, close down listen. if(MaxConnections > 0 && ConnectionCount > MaxConnections && LinkState == STATE_Listening) { Log("WebServer: Too many connections - closing down Listen."); Close(); } } event LostChild( Actor C ) { Super.LostChild(C); ConnectionCount--; // if closed due to too many connections, start listening again. if(ConnectionCount <= MaxConnections && LinkState != STATE_Listening) { Log("WebServer: Listening again - connections have been closed."); Listen(); } } function WebApplication GetApplication(string URI, out string SubURI) { local int i, l; SubURI = ""; for(i=0;i<10;i++) { if(ApplicationPaths[i] != "") { l = Len(ApplicationPaths[i]); if(Left(URI, l) == ApplicationPaths[i] && (Len(URI) == l || Mid(URI, l, 1) == "/")) { SubURI = Mid(URI, l); return ApplicationObjects[i]; } } } return None; } defaultproperties { Applications(0)="xWebAdmin.UTServerAdmin" Applications(1)="xWebAdmin.UTImageServer" ApplicationPaths(0)="/ServerAdmin" ApplicationPaths(1)="/images" ListenPort=8075 MaxConnections=30 ExpirationSeconds=86400 AcceptClass=Class'UWeb.WebConnection' }