aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorDiva Canto2011-06-12 15:37:42 -0700
committerDiva Canto2011-06-12 15:37:42 -0700
commitfd57c91b4a10cf7ee1e94dc8fe4e81eb0d5bae3d (patch)
tree55907fbcea5962638275453301482190c4b989b0 /OpenSim
parentA few more cleanups on the way to close http://opensimulator.org/mantis/view.... (diff)
downloadopensim-SC_OLD-fd57c91b4a10cf7ee1e94dc8fe4e81eb0d5bae3d.zip
opensim-SC_OLD-fd57c91b4a10cf7ee1e94dc8fe4e81eb0d5bae3d.tar.gz
opensim-SC_OLD-fd57c91b4a10cf7ee1e94dc8fe4e81eb0d5bae3d.tar.bz2
opensim-SC_OLD-fd57c91b4a10cf7ee1e94dc8fe4e81eb0d5bae3d.tar.xz
First pass at making the V2 map work. Standalones only for now. There are some issues with the zoom level -- TBD.
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs111
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs232
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs8
-rw-r--r--OpenSim/Server/Handlers/Map/MapAddServerConnector.cs61
-rw-r--r--OpenSim/Server/Handlers/Map/MapGetServerConnector.cs105
-rw-r--r--OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs158
-rw-r--r--OpenSim/Services/Interfaces/IMapImageService.cs (renamed from OpenSim/Services/Interfaces/IMapService.cs)6
-rw-r--r--OpenSim/Services/MapImageService/MapImageService.cs295
9 files changed, 972 insertions, 8 deletions
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 598e5d1..cb1117a 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -412,7 +412,7 @@ namespace OpenSim.Framework.Servers.HttpServer
412 // OpenSim.Framework.WebUtil.OSHeaderRequestID 412 // OpenSim.Framework.WebUtil.OSHeaderRequestID
413 if (request.Headers["opensim-request-id"] != null) 413 if (request.Headers["opensim-request-id"] != null)
414 reqnum = String.Format("{0}:{1}",request.RemoteIPEndPoint,request.Headers["opensim-request-id"]); 414 reqnum = String.Format("{0}:{1}",request.RemoteIPEndPoint,request.Headers["opensim-request-id"]);
415 // m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl); 415 //m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl);
416 416
417 Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); 417 Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true);
418 418
@@ -440,7 +440,7 @@ namespace OpenSim.Framework.Servers.HttpServer
440 string path = request.RawUrl; 440 string path = request.RawUrl;
441 string handlerKey = GetHandlerKey(request.HttpMethod, path); 441 string handlerKey = GetHandlerKey(request.HttpMethod, path);
442 442
443// m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); 443 //m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path);
444 444
445 if (TryGetStreamHandler(handlerKey, out requestHandler)) 445 if (TryGetStreamHandler(handlerKey, out requestHandler))
446 { 446 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs
new file mode 100644
index 0000000..b570155
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs
@@ -0,0 +1,111 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Reflection;
30using System.Collections.Generic;
31using log4net;
32using Mono.Addins;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Server.Base;
38using OpenSim.Server.Handlers.Base;
39using OpenSim.Server.Handlers.MapImage;
40using OpenSim.Services.Interfaces;
41
42namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.MapImage
43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
45 public class MapImageServiceInConnectorModule : ISharedRegionModule
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 private static bool m_Enabled = false;
49
50 private IConfigSource m_Config;
51 bool m_Registered = false;
52
53 #region IRegionModule interface
54
55 public void Initialise(IConfigSource config)
56 {
57 m_Config = config;
58 IConfig moduleConfig = config.Configs["Modules"];
59 if (moduleConfig != null)
60 {
61 m_Enabled = moduleConfig.GetBoolean("MapImageServiceInConnector", false);
62 if (m_Enabled)
63 {
64 m_log.Info("[MAP SERVICE IN CONNECTOR]: MapImage Service In Connector enabled");
65 new MapGetServiceConnector(m_Config, MainServer.Instance, "MapImageService");
66 }
67
68 }
69
70 }
71
72 public void PostInitialise()
73 {
74 }
75
76 public void Close()
77 {
78 }
79
80 public Type ReplaceableInterface
81 {
82 get { return null; }
83 }
84
85 public string Name
86 {
87 get { return "MapImageServiceIn"; }
88 }
89
90 public void AddRegion(Scene scene)
91 {
92 if (!m_Enabled)
93 return;
94 }
95
96 public void RemoveRegion(Scene scene)
97 {
98 if (!m_Enabled)
99 return;
100 }
101
102 public void RegionLoaded(Scene scene)
103 {
104 if (!m_Enabled)
105 return;
106 }
107
108 #endregion
109
110 }
111}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
new file mode 100644
index 0000000..ee90859
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
@@ -0,0 +1,232 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Net;
32using System.IO;
33using System.Timers;
34using System.Drawing;
35using System.Drawing.Imaging;
36
37using log4net;
38using Mono.Addins;
39using Nini.Config;
40using OpenSim.Framework;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Services.Interfaces;
44using OpenSim.Server.Base;
45using OpenMetaverse;
46using OpenMetaverse.StructuredData;
47
48namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
49{
50 /// <summary>
51 /// </summary>
52 /// <remarks>
53 /// </remarks>
54
55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
56 public class MapImageServiceModule : ISharedRegionModule
57 {
58 private static readonly ILog m_log =
59 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
60
61 private bool m_enabled = false;
62 private IMapImageService m_MapService;
63
64 private string m_serverUrl = String.Empty;
65 private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
66
67 private int m_refreshtime = 0;
68 private int m_lastrefresh = 0;
69 private System.Timers.Timer m_refreshTimer = new System.Timers.Timer();
70
71 #region ISharedRegionModule
72
73 public Type ReplaceableInterface { get { return null; } }
74 public string Name { get { return "MapImageServiceModule"; } }
75 public void RegionLoaded(Scene scene) { }
76 public void Close() { }
77 public void PostInitialise() { }
78
79
80 ///<summary>
81 ///
82 ///</summary>
83 public void Initialise(IConfigSource source)
84 {
85 IConfig moduleConfig = source.Configs["Modules"];
86 if (moduleConfig != null)
87 {
88 string name = moduleConfig.GetString("MapImageService", "");
89 if (name != Name)
90 return;
91 }
92
93 IConfig config = source.Configs["MapImageService"];
94 if (config == null)
95 return;
96
97 int refreshminutes = Convert.ToInt32(config.GetString("RefreshTime"));
98 if (refreshminutes <= 0)
99 {
100 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: No refresh time given in config. Module disabled.");
101 return;
102 }
103
104 m_refreshtime = refreshminutes * 60 * 1000; // convert from minutes to ms
105
106 string service = config.GetString("LocalServiceModule", string.Empty);
107 if (service == string.Empty)
108 {
109 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: No service dll given in config. Unable to proceed.");
110 return;
111 }
112
113 Object[] args = new Object[] { source };
114 m_MapService = ServerUtils.LoadPlugin<IMapImageService>(service, args);
115
116 m_refreshTimer.Enabled = true;
117 m_refreshTimer.AutoReset = true;
118 m_refreshTimer.Interval = m_refreshtime;
119 m_refreshTimer.Elapsed += new ElapsedEventHandler(HandleMaptileRefresh);
120
121 m_log.InfoFormat("[MAP IMAGE SERVICE MODULE]: enabled with refresh time {0}min and service object {1}",
122 refreshminutes, service);
123
124 m_enabled = true;
125 }
126
127 ///<summary>
128 ///
129 ///</summary>
130
131
132 ///<summary>
133 ///
134 ///</summary>
135 public void AddRegion(Scene scene)
136 {
137 if (! m_enabled)
138 return;
139
140 // Every shared region module has to maintain an indepedent list of
141 // currently running regions
142 lock (m_scenes)
143 m_scenes[scene.RegionInfo.RegionID] = scene;
144
145 scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded);
146 }
147
148 ///<summary>
149 ///
150 ///</summary>
151 public void RemoveRegion(Scene scene)
152 {
153 if (! m_enabled)
154 return;
155
156 lock (m_scenes)
157 m_scenes.Remove(scene.RegionInfo.RegionID);
158 }
159
160 #endregion ISharedRegionModule
161
162 void EventManager_OnPrimsLoaded(Scene s)
163 {
164 UploadMapTile(s);
165 }
166
167
168 ///<summary>
169 ///
170 ///</summary>
171 private void HandleMaptileRefresh(object sender, EventArgs ea)
172 {
173 // this approach is a bit convoluted becase we want to wait for the
174 // first upload to happen on startup but after all the objects are
175 // loaded and initialized
176 if (m_lastrefresh > 0 && Util.EnvironmentTickCountSubtract(m_lastrefresh) < m_refreshtime)
177 return;
178
179 m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: map refresh!");
180 lock (m_scenes)
181 {
182 foreach (IScene scene in m_scenes.Values)
183 {
184 try
185 {
186 UploadMapTile(scene);
187 }
188 catch (Exception ex)
189 {
190 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: something bad happened {0}", ex.Message);
191 }
192 }
193 }
194
195 m_lastrefresh = Util.EnvironmentTickCount();
196 }
197
198 ///<summary>
199 ///
200 ///</summary>
201 private void UploadMapTile(IScene scene)
202 {
203 m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: upload maptile for {0}", scene.RegionInfo.RegionName);
204
205 // Create a PNG map tile and upload it to the AddMapTile API
206 byte[] jpgData = Utils.EmptyBytes;
207 IMapImageGenerator tileGenerator = scene.RequestModuleInterface<IMapImageGenerator>();
208 if (tileGenerator == null)
209 {
210 m_log.Warn("[MAP IMAGE SERVICE MODULE]: Cannot upload PNG map tile without an ImageGenerator");
211 return;
212 }
213
214 using (Image mapTile = tileGenerator.CreateMapTile())
215 {
216 using (MemoryStream stream = new MemoryStream())
217 {
218 mapTile.Save(stream, ImageFormat.Jpeg);
219 jpgData = stream.ToArray();
220 }
221 }
222
223 string reason = string.Empty;
224 if (!m_MapService.AddMapTile((int)scene.RegionInfo.RegionLocX, (int)scene.RegionInfo.RegionLocY, jpgData, out reason))
225 {
226 m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: Unable to upload tile image for {0} at {1}-{2}: {3}",
227 scene.RegionInfo.RegionName, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY, reason);
228 }
229
230 }
231 }
232} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index 3553c9a..079b1c2 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -849,10 +849,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
849 { 849 {
850 List<MapBlockData> mapBlocks = new List<MapBlockData>(); 850 List<MapBlockData> mapBlocks = new List<MapBlockData>();
851 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 851 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
852 (minX - 4) * (int)Constants.RegionSize, 852 (minX - 8) * (int)Constants.RegionSize,
853 (maxX + 4) * (int)Constants.RegionSize, 853 (maxX + 8) * (int)Constants.RegionSize,
854 (minY - 4) * (int)Constants.RegionSize, 854 (minY - 8) * (int)Constants.RegionSize,
855 (maxY + 4) * (int)Constants.RegionSize); 855 (maxY + 8) * (int)Constants.RegionSize);
856 foreach (GridRegion r in regions) 856 foreach (GridRegion r in regions)
857 { 857 {
858 MapBlockData block = new MapBlockData(); 858 MapBlockData block = new MapBlockData();
diff --git a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs
new file mode 100644
index 0000000..a953cd7
--- /dev/null
+++ b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs
@@ -0,0 +1,61 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using Nini.Config;
30using OpenSim.Server.Base;
31using OpenSim.Services.Interfaces;
32using OpenSim.Framework.Servers.HttpServer;
33using OpenSim.Server.Handlers.Base;
34
35namespace OpenSim.Server.Handlers.MapImage
36{
37 public class MapAddServiceConnector : ServiceConnector
38 {
39 private IMapImageService m_MapService;
40 private string m_ConfigName = "MapImageService";
41
42 public MapAddServiceConnector(IConfigSource config, IHttpServer server, string configName) :
43 base(config, server, configName)
44 {
45 IConfig serverConfig = config.Configs[m_ConfigName];
46 if (serverConfig == null)
47 throw new Exception(String.Format("No section {0} in config file", m_ConfigName));
48
49 string gridService = serverConfig.GetString("LocalServiceModule",
50 String.Empty);
51
52 if (gridService == String.Empty)
53 throw new Exception("No LocalServiceModule in config file");
54
55 Object[] args = new Object[] { config };
56 m_MapService = ServerUtils.LoadPlugin<IMapImageService>(gridService, args);
57
58 //server.AddStreamHandler(new PresenceServerPostHandler(m_PresenceService));
59 }
60 }
61}
diff --git a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs
new file mode 100644
index 0000000..9448af7
--- /dev/null
+++ b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs
@@ -0,0 +1,105 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.IO;
30using System.Net;
31using System.Reflection;
32
33using Nini.Config;
34using log4net;
35
36using OpenSim.Server.Base;
37using OpenSim.Services.Interfaces;
38using OpenSim.Framework.Servers.HttpServer;
39using OpenSim.Server.Handlers.Base;
40
41namespace OpenSim.Server.Handlers.MapImage
42{
43 public class MapGetServiceConnector : ServiceConnector
44 {
45 private IMapImageService m_MapService;
46 private string m_ConfigName = "MapImageService";
47
48 public MapGetServiceConnector(IConfigSource config, IHttpServer server, string configName) :
49 base(config, server, configName)
50 {
51 IConfig serverConfig = config.Configs[m_ConfigName];
52 if (serverConfig == null)
53 throw new Exception(String.Format("No section {0} in config file", m_ConfigName));
54
55 string gridService = serverConfig.GetString("LocalServiceModule",
56 String.Empty);
57
58 if (gridService == String.Empty)
59 throw new Exception("No LocalServiceModule in config file");
60
61 Object[] args = new Object[] { config };
62 m_MapService = ServerUtils.LoadPlugin<IMapImageService>(gridService, args);
63
64 server.AddStreamHandler(new MapServerGetHandler(m_MapService));
65 }
66 }
67
68 class MapServerGetHandler : BaseStreamHandler
69 {
70 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
71 private IMapImageService m_MapService;
72
73 public MapServerGetHandler(IMapImageService service) :
74 base("GET", "/map")
75 {
76 m_MapService = service;
77 }
78
79 public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
80 {
81 m_log.DebugFormat("[MAP SERVICE IMAGE HANDLER]: retrieving {0}", path);
82 byte[] result = new byte[0];
83
84 string format = string.Empty;
85 result = m_MapService.GetMapTile(path.Trim('/'), out format);
86
87 if (result.Length > 0)
88 {
89 httpResponse.StatusCode = (int)HttpStatusCode.OK;
90 if (format.Equals("png"))
91 httpResponse.ContentType = "image/png";
92 else if (format.Equals("jpg") || format.Equals("jpeg"))
93 httpResponse.ContentType = "image/jpeg";
94 }
95 else
96 {
97 httpResponse.StatusCode = (int)HttpStatusCode.NotFound;
98 httpResponse.ContentType = "text/plain";
99 }
100
101 return result;
102 }
103
104 }
105}
diff --git a/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs b/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs
new file mode 100644
index 0000000..ff0e9d9
--- /dev/null
+++ b/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs
@@ -0,0 +1,158 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using log4net;
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Net;
33using System.Reflection;
34
35using Nini.Config;
36using OpenSim.Framework;
37using OpenSim.Framework.Console;
38using OpenSim.Framework.Communications;
39using OpenSim.Services.Interfaces;
40using OpenMetaverse;
41using OpenMetaverse.StructuredData;
42
43namespace OpenSim.Services.Connectors
44{
45 public class MapImageServicesConnector : IMapImageService
46 {
47 private static readonly ILog m_log =
48 LogManager.GetLogger(
49 MethodBase.GetCurrentMethod().DeclaringType);
50
51 private string m_ServerURI = String.Empty;
52 private IImprovedAssetCache m_Cache = null;
53
54 public MapImageServicesConnector()
55 {
56 }
57
58 public MapImageServicesConnector(string serverURI)
59 {
60 m_ServerURI = serverURI.TrimEnd('/');
61 }
62
63 public MapImageServicesConnector(IConfigSource source)
64 {
65 Initialise(source);
66 }
67
68 public virtual void Initialise(IConfigSource source)
69 {
70 IConfig config = source.Configs["MapImageService"];
71 if (config == null)
72 {
73 m_log.Error("[MAP IMAGE CONNECTOR]: MapImageService missing");
74 throw new Exception("MapImage connector init error");
75 }
76
77 string serviceURI = config.GetString("MapImageServerURI",
78 String.Empty);
79
80 if (serviceURI == String.Empty)
81 {
82 m_log.Error("[MAP IMAGE CONNECTOR]: No Server URI named in section MapImageService");
83 throw new Exception("MapImage connector init error");
84 }
85 m_ServerURI = serviceURI;
86 }
87
88 public bool AddMapTile(int x, int y, byte[] pngData, out string reason)
89 {
90 List<MultipartForm.Element> postParameters = new List<MultipartForm.Element>()
91 {
92 new MultipartForm.Parameter("X", x.ToString()),
93 new MultipartForm.Parameter("Y", y.ToString()),
94 new MultipartForm.File("Tile", "tile.png", "image/png", pngData)
95 };
96
97 reason = string.Empty;
98 int tickstart = Util.EnvironmentTickCount();
99
100 // Make the remote storage request
101 try
102 {
103 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_ServerURI);
104 request.Timeout = 20000;
105 request.ReadWriteTimeout = 5000;
106
107 using (HttpWebResponse response = MultipartForm.Post(request, postParameters))
108 {
109 using (Stream responseStream = response.GetResponseStream())
110 {
111 string responseStr = responseStream.GetStreamString();
112 OSD responseOSD = OSDParser.Deserialize(responseStr);
113 if (responseOSD.Type == OSDType.Map)
114 {
115 OSDMap responseMap = (OSDMap)responseOSD;
116 if (responseMap["Success"].AsBoolean())
117 return true;
118
119 reason = "Upload failed: " + responseMap["Message"].AsString();
120 }
121 else
122 {
123 reason = "Response format was invalid:\n" + responseStr;
124 }
125 }
126 }
127 }
128 catch (WebException we)
129 {
130 reason = we.Message;
131 if (we.Status == WebExceptionStatus.ProtocolError)
132 {
133 HttpWebResponse webResponse = (HttpWebResponse)we.Response;
134 reason = String.Format("[{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription);
135 }
136 }
137 catch (Exception ex)
138 {
139 reason = ex.Message;
140 }
141 finally
142 {
143 // This just dumps a warning for any operation that takes more than 100 ms
144 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
145 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: map tile uploaded in {0}ms", tickdiff);
146 }
147
148 return false;
149 }
150
151 public byte[] GetMapTile(string fileName, out string format)
152 {
153 format = string.Empty;
154 new Exception("GetMapTile method not Implemented");
155 return null;
156 }
157 }
158}
diff --git a/OpenSim/Services/Interfaces/IMapService.cs b/OpenSim/Services/Interfaces/IMapImageService.cs
index c70f484..a7b2cf1 100644
--- a/OpenSim/Services/Interfaces/IMapService.cs
+++ b/OpenSim/Services/Interfaces/IMapImageService.cs
@@ -31,8 +31,10 @@ using OpenMetaverse;
31 31
32namespace OpenSim.Services.Interfaces 32namespace OpenSim.Services.Interfaces
33{ 33{
34 public interface IMapService 34 public interface IMapImageService
35 { 35 {
36 List<MapBlockData> GetMapBlocks(UUID scopeID, int minX, int minY, int maxX, int maxY); 36 //List<MapBlockData> GetMapBlocks(UUID scopeID, int minX, int minY, int maxX, int maxY);
37 bool AddMapTile(int x, int y, byte[] imageData, out string reason);
38 byte[] GetMapTile(string fileName, out string format);
37 } 39 }
38} 40}
diff --git a/OpenSim/Services/MapImageService/MapImageService.cs b/OpenSim/Services/MapImageService/MapImageService.cs
new file mode 100644
index 0000000..596c4a6
--- /dev/null
+++ b/OpenSim/Services/MapImageService/MapImageService.cs
@@ -0,0 +1,295 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Drawing;
31using System.Drawing.Imaging;
32using System.IO;
33using System.Net;
34using System.Reflection;
35
36using Nini.Config;
37using log4net;
38using OpenMetaverse;
39
40using OpenSim.Framework;
41using OpenSim.Framework.Console;
42using OpenSim.Services.Interfaces;
43
44
45namespace OpenSim.Services.MapImageService
46{
47 public class MapImageService : IMapImageService
48 {
49 private static readonly ILog m_log =
50 LogManager.GetLogger(
51 MethodBase.GetCurrentMethod().DeclaringType);
52
53 private const int ZOOM_LEVELS = 8;
54 private const int IMAGE_WIDTH = 256;
55 private const int HALF_WIDTH = 128;
56 private const int JPEG_QUALITY = 80;
57
58 private static string m_TilesStoragePath = "maptiles";
59
60 private static object m_Sync = new object();
61 private static bool m_Initialized = false;
62 private static string m_WaterTileFile = string.Empty;
63 private static Color m_Watercolor = Color.FromArgb(29, 71, 95);
64
65 public MapImageService(IConfigSource config)
66 {
67 if (!m_Initialized)
68 {
69 m_Initialized = true;
70 m_log.Debug("[MAP IMAGE SERVICE]: Starting MapImage service");
71
72 IConfig serviceConfig = config.Configs["MapImageService"];
73 if (serviceConfig != null)
74 {
75 m_TilesStoragePath = serviceConfig.GetString("TilesStoragePath", m_TilesStoragePath);
76 if (!Directory.Exists(m_TilesStoragePath))
77 Directory.CreateDirectory(m_TilesStoragePath);
78
79
80 m_WaterTileFile = Path.Combine(m_TilesStoragePath, "water.jpg");
81 if (!File.Exists(m_WaterTileFile))
82 {
83 Bitmap waterTile = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH);
84 FillImage(waterTile, m_Watercolor);
85 waterTile.Save(m_WaterTileFile);
86 }
87 }
88 }
89 }
90
91 #region IMapImageService
92
93 public bool AddMapTile(int x, int y, byte[] imageData, out string reason)
94 {
95 reason = string.Empty;
96 string fileName = GetFileName(1, x, y);
97
98 lock (m_Sync)
99 {
100 try
101 {
102 using (FileStream f = File.Open(fileName, FileMode.OpenOrCreate, FileAccess.Write))
103 f.Write(imageData, 0, imageData.Length);
104 }
105 catch (Exception e)
106 {
107 m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to save image file {0}: {1}", fileName, e);
108 reason = e.Message;
109 return false;
110 }
111
112 // Also save in png format?
113
114 // Stitch seven more aggregate tiles together
115 for (uint zoomLevel = 2; zoomLevel <= ZOOM_LEVELS; zoomLevel++)
116 {
117 // Calculate the width (in full resolution tiles) and bottom-left
118 // corner of the current zoom level
119 int width = (int)Math.Pow(2, (double)(zoomLevel - 1));
120 int x1 = x - (x % width);
121 int y1 = y - (y % width);
122
123 if (!CreateTile(zoomLevel, x1, y1))
124 {
125 m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to create tile for {0} at zoom level {1}", fileName, zoomLevel);
126 reason = string.Format("Map tile at zoom level {0} failed", zoomLevel);
127 return false;
128 }
129 }
130 }
131
132 return true;
133 }
134
135 public byte[] GetMapTile(string fileName, out string format)
136 {
137 format = "jpg";
138 string fullName = Path.Combine(m_TilesStoragePath, fileName);
139 if (File.Exists(fullName))
140 {
141 format = Path.GetExtension(fileName).ToLower();
142 m_log.DebugFormat("[MAP IMAGE SERVICE]: Found file {0}, extension {1}", fileName, format);
143 return File.ReadAllBytes(fullName);
144 }
145 else if (File.Exists(m_WaterTileFile))
146 {
147 m_log.DebugFormat("[MAP IMAGE SERVICE]: File not found {0}, sending water", fileName);
148 return File.ReadAllBytes(m_WaterTileFile);
149 }
150 else
151 {
152 m_log.DebugFormat("[MAP IMAGE SERVICE]: unable to get file {0}", fileName);
153 return new byte[0];
154 }
155 }
156
157 #endregion
158
159
160 private string GetFileName(uint zoomLevel, int x, int y)
161 {
162 string extension = "jpg";
163 return Path.Combine(m_TilesStoragePath, string.Format("map-{0}-{1}-{2}-objects.{3}", zoomLevel, x, y, extension));
164 }
165
166 private Bitmap GetInputTileImage(string fileName)
167 {
168 try
169 {
170 if (File.Exists(fileName))
171 return new Bitmap(fileName);
172 }
173 catch (Exception e)
174 {
175 m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to read image data from {0}: {1}", fileName, e);
176 }
177
178 return null;
179 }
180
181 private Bitmap GetOutputTileImage(string fileName)
182 {
183 try
184 {
185 if (File.Exists(fileName))
186 return new Bitmap(fileName);
187
188 else
189 {
190 // Create a new output tile with a transparent background
191 Bitmap bm = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH);
192 bm.MakeTransparent();
193 return bm;
194 }
195 }
196 catch (Exception e)
197 {
198 m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to read image data from {0}: {1}", fileName, e);
199 }
200
201 return null;
202 }
203
204 private bool CreateTile(uint zoomLevel, int x, int y)
205 {
206 m_log.DebugFormat("[MAP IMAGE SERVICE]: Create tile for {0} {1}, zoom {2}", x, y, zoomLevel);
207 int prevWidth = (int)Math.Pow(2, (double)zoomLevel - 2);
208 int thisWidth = (int)Math.Pow(2, (double)zoomLevel - 1);
209
210 // Convert x and y to the bottom left tile for this zoom level
211 int xIn = x - (x % prevWidth);
212 int yIn = y - (y % prevWidth);
213
214 // Convert x and y to the bottom left tile for the next zoom level
215 int xOut = x - (x % thisWidth);
216 int yOut = y - (y % thisWidth);
217
218 // Try to open the four input tiles from the previous zoom level
219 Bitmap inputBL = GetInputTileImage(GetFileName(zoomLevel - 1, xIn, yIn));
220 Bitmap inputBR = GetInputTileImage(GetFileName(zoomLevel - 1, xIn + prevWidth, yIn));
221 Bitmap inputTL = GetInputTileImage(GetFileName(zoomLevel - 1, xIn, yIn + prevWidth));
222 Bitmap inputTR = GetInputTileImage(GetFileName(zoomLevel - 1, xIn + prevWidth, yIn + prevWidth));
223
224 // Open the output tile (current zoom level)
225 string outputFile = GetFileName(zoomLevel, xOut, yOut);
226 Bitmap output = GetOutputTileImage(outputFile);
227 if (output == null)
228 return false;
229 FillImage(output, m_Watercolor);
230
231 if (inputBL != null)
232 {
233 ImageCopyResampled(output, inputBL, 0, HALF_WIDTH, 0, 0);
234 inputBL.Dispose();
235 }
236 if (inputBR != null)
237 {
238 ImageCopyResampled(output, inputBR, HALF_WIDTH, HALF_WIDTH, 0, 0);
239 inputBR.Dispose();
240 }
241 if (inputTL != null)
242 {
243 ImageCopyResampled(output, inputTL, 0, 0, 0, 0);
244 inputTL.Dispose();
245 }
246 if (inputTR != null)
247 {
248 ImageCopyResampled(output, inputTR, HALF_WIDTH, 0, 0, 0);
249 inputTR.Dispose();
250 }
251
252 // Write the modified output
253 try
254 {
255 using (Bitmap final = new Bitmap(output))
256 {
257 output.Dispose();
258 final.Save(outputFile);
259 }
260 }
261 catch (Exception e)
262 {
263 m_log.WarnFormat("[MAP IMAGE SERVICE]: Oops on saving {0} {1}", outputFile, e);
264 }
265
266 // Save also as png?
267
268 return true;
269 }
270
271 #region Image utilities
272
273 private void FillImage(Bitmap bm, Color c)
274 {
275 for (int x = 0; x < bm.Width; x++)
276 for (int y = 0; y < bm.Height; y++)
277 bm.SetPixel(x, y, c);
278 }
279
280 private void ImageCopyResampled(Bitmap output, Bitmap input, int destX, int destY, int srcX, int srcY)
281 {
282 int resamplingRateX = 2; // (input.Width - srcX) / (output.Width - destX);
283 int resamplingRateY = 2; // (input.Height - srcY) / (output.Height - destY);
284
285 for (int x = destX; x < destX + HALF_WIDTH; x++)
286 for (int y = destY; y < destY + HALF_WIDTH; y++)
287 {
288 Color p = input.GetPixel(srcX + (x - destX) * resamplingRateX, srcY + (y - destY) * resamplingRateY);
289 output.SetPixel(x, y, p);
290 }
291 }
292
293 #endregion
294 }
295}