diff options
Diffstat (limited to 'OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server')
-rw-r--r-- | OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs | 202 |
1 files changed, 147 insertions, 55 deletions
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index e87749c..bb20dfd 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs | |||
@@ -1,5 +1,6 @@ | |||
1 | using System; | 1 | using System; |
2 | using System.Collections.Generic; | 2 | using System.Collections.Generic; |
3 | using System.IO; | ||
3 | using System.Net; | 4 | using System.Net; |
4 | using System.Net.Sockets; | 5 | using System.Net.Sockets; |
5 | using System.Reflection; | 6 | using System.Reflection; |
@@ -14,8 +15,12 @@ using OpenSim.Region.Framework.Scenes; | |||
14 | 15 | ||
15 | namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | 16 | namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server |
16 | { | 17 | { |
18 | public delegate void OnIRCClientReadyDelegate(IRCClientView cv); | ||
19 | |||
17 | public class IRCClientView : IClientAPI, IClientCore, IClientIPEndpoint | 20 | public class IRCClientView : IClientAPI, IClientCore, IClientIPEndpoint |
18 | { | 21 | { |
22 | public event OnIRCClientReadyDelegate OnIRCReady; | ||
23 | |||
19 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 24 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
20 | 25 | ||
21 | private readonly TcpClient m_client; | 26 | private readonly TcpClient m_client; |
@@ -24,6 +29,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
24 | private UUID m_agentID = UUID.Random(); | 29 | private UUID m_agentID = UUID.Random(); |
25 | 30 | ||
26 | private string m_username; | 31 | private string m_username; |
32 | private string m_nick; | ||
27 | 33 | ||
28 | private bool m_hasNick = false; | 34 | private bool m_hasNick = false; |
29 | private bool m_hasUser = false; | 35 | private bool m_hasUser = false; |
@@ -39,16 +45,23 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
39 | loopThread.Start(); | 45 | loopThread.Start(); |
40 | } | 46 | } |
41 | 47 | ||
48 | private void SendServerCommand(string command) | ||
49 | { | ||
50 | SendCommand(":opensimircd " + command); | ||
51 | } | ||
52 | |||
42 | private void SendCommand(string command) | 53 | private void SendCommand(string command) |
43 | { | 54 | { |
44 | lock(m_client) | 55 | m_log.Info("[IRCd] Sending >>> " + command); |
45 | { | ||
46 | m_log.Info("[IRCd] Sending >>> " + command); | ||
47 | 56 | ||
48 | byte[] buf = Encoding.UTF8.GetBytes(command + "\r\n"); | 57 | byte[] buf = Encoding.UTF8.GetBytes(command + "\r\n"); |
49 | 58 | ||
50 | m_client.GetStream().Write(buf, 0, buf.Length); | 59 | m_client.GetStream().BeginWrite(buf, 0, buf.Length, SendComplete, null); |
51 | } | 60 | } |
61 | |||
62 | private void SendComplete(IAsyncResult result) | ||
63 | { | ||
64 | m_log.Info("[IRCd] Send Complete."); | ||
52 | } | 65 | } |
53 | 66 | ||
54 | private string IrcRegionName | 67 | private string IrcRegionName |
@@ -60,40 +73,67 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
60 | 73 | ||
61 | private void InternalLoop() | 74 | private void InternalLoop() |
62 | { | 75 | { |
63 | string strbuf = ""; | 76 | try |
64 | |||
65 | while(m_connected) | ||
66 | { | 77 | { |
67 | string line; | 78 | string strbuf = ""; |
68 | byte[] buf = new byte[520]; // RFC1459 defines max message size as 512. | ||
69 | 79 | ||
70 | lock (m_client) | 80 | while (m_connected && m_client.Connected) |
71 | { | 81 | { |
82 | byte[] buf = new byte[8]; // RFC1459 defines max message size as 512. | ||
83 | |||
72 | int count = m_client.GetStream().Read(buf, 0, buf.Length); | 84 | int count = m_client.GetStream().Read(buf, 0, buf.Length); |
73 | line = Encoding.UTF8.GetString(buf, 0, count); | 85 | string line = Encoding.UTF8.GetString(buf, 0, count); |
74 | } | ||
75 | 86 | ||
76 | strbuf += line; | 87 | strbuf += line; |
77 | 88 | ||
78 | string message = ExtractMessage(strbuf); | 89 | string message = ExtractMessage(strbuf); |
79 | if(message != null) | 90 | if (message != null) |
80 | { | 91 | { |
81 | m_log.Info("[IRCd] Recieving <<< " + message); | 92 | // Remove from buffer |
93 | strbuf = strbuf.Remove(0, message.Length); | ||
94 | |||
95 | m_log.Info("[IRCd] Recieving <<< " + message); | ||
96 | message = message.Trim(); | ||
82 | 97 | ||
83 | // Remove from buffer | 98 | // Extract command sequence |
84 | strbuf = strbuf.Remove(0, message.Length); | 99 | string command = ExtractCommand(message); |
100 | ProcessInMessage(message, command); | ||
101 | } | ||
102 | else | ||
103 | { | ||
104 | //m_log.Info("[IRCd] Recieved data, but not enough to make a message. BufLen is " + strbuf.Length + | ||
105 | // "[" + strbuf + "]"); | ||
106 | if (strbuf.Length == 0) | ||
107 | { | ||
108 | m_connected = false; | ||
109 | m_log.Info("[IRCd] Buffer zero, closing..."); | ||
110 | if (OnDisconnectUser != null) | ||
111 | OnDisconnectUser(); | ||
112 | } | ||
113 | } | ||
85 | 114 | ||
86 | // Extract command sequence | 115 | Thread.Sleep(0); |
87 | string command = ExtractCommand(message); | ||
88 | ProcessInMessage(message, command); | ||
89 | } | 116 | } |
117 | } | ||
118 | catch (IOException) | ||
119 | { | ||
120 | if (OnDisconnectUser != null) | ||
121 | OnDisconnectUser(); | ||
122 | |||
123 | m_log.Warn("[IRCd] Disconnected client."); | ||
124 | } | ||
125 | catch (SocketException) | ||
126 | { | ||
127 | if (OnDisconnectUser != null) | ||
128 | OnDisconnectUser(); | ||
90 | 129 | ||
91 | Thread.Sleep(0); | 130 | m_log.Warn("[IRCd] Disconnected client."); |
92 | } | 131 | } |
93 | } | 132 | } |
94 | 133 | ||
95 | private void ProcessInMessage(string message, string command) | 134 | private void ProcessInMessage(string message, string command) |
96 | { | 135 | { |
136 | m_log.Info("[IRCd] Processing [MSG:" + message + "] [COM:" + command + "]"); | ||
97 | if(command != null) | 137 | if(command != null) |
98 | { | 138 | { |
99 | switch(command) | 139 | switch(command) |
@@ -123,12 +163,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
123 | case "SUMMON": | 163 | case "SUMMON": |
124 | case "TIME": | 164 | case "TIME": |
125 | case "TRACE": | 165 | case "TRACE": |
126 | case "USERHOST": | ||
127 | case "VERSION": | 166 | case "VERSION": |
128 | case "WALLOPS": | 167 | case "WALLOPS": |
129 | case "WHOIS": | 168 | case "WHOIS": |
130 | case "WHOWAS": | 169 | case "WHOWAS": |
131 | SendCommand("421 ERR_UNKNOWNCOMMAND \"" + command + " :Command unimplemented\""); | 170 | SendServerCommand("421 " + command + " :Command unimplemented"); |
132 | break; | 171 | break; |
133 | 172 | ||
134 | // Connection Commands | 173 | // Connection Commands |
@@ -141,12 +180,20 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
141 | 180 | ||
142 | case "USER": | 181 | case "USER": |
143 | IRC_ProcessUser(message); | 182 | IRC_ProcessUser(message); |
144 | IRC_SendReplyJoin(); | 183 | IRC_Ready(); |
184 | break; | ||
145 | 185 | ||
186 | case "USERHOST": | ||
187 | string[] userhostArgs = ExtractParameters(message); | ||
188 | if (userhostArgs[0] == ":" + m_nick) | ||
189 | { | ||
190 | SendServerCommand("302 :" + m_nick + "=+" + m_nick + "@" + | ||
191 | ((IPEndPoint) m_client.Client.RemoteEndPoint).Address); | ||
192 | } | ||
146 | break; | 193 | break; |
147 | case "NICK": | 194 | case "NICK": |
148 | IRC_ProcessNick(message); | 195 | IRC_ProcessNick(message); |
149 | IRC_SendReplyJoin(); | 196 | IRC_Ready(); |
150 | 197 | ||
151 | break; | 198 | break; |
152 | case "TOPIC": | 199 | case "TOPIC": |
@@ -164,7 +211,10 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
164 | break; | 211 | break; |
165 | 212 | ||
166 | case "NOTICE": // TODO | 213 | case "NOTICE": // TODO |
214 | break; | ||
215 | |||
167 | case "WHO": // TODO | 216 | case "WHO": // TODO |
217 | IRC_SendWhoReply(); | ||
168 | break; | 218 | break; |
169 | 219 | ||
170 | case "PING": | 220 | case "PING": |
@@ -188,31 +238,55 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
188 | break; | 238 | break; |
189 | 239 | ||
190 | default: | 240 | default: |
191 | SendCommand("421 ERR_UNKNOWNCOMMAND \"" + command + " :Unknown command\""); | 241 | SendServerCommand("421 " + command + " :Unknown command"); |
192 | break; | 242 | break; |
193 | } | 243 | } |
194 | } | 244 | } |
195 | } | 245 | } |
196 | 246 | ||
197 | private void IRC_SendReplyJoin() | 247 | private void IRC_Ready() |
198 | { | 248 | { |
199 | if (m_hasUser && m_hasNick) | 249 | if (m_hasUser && m_hasNick) |
200 | { | 250 | { |
201 | IRC_SendReplyTopic(); | 251 | SendServerCommand("001 " + m_nick + " :Welcome to OpenSimulator IRCd"); |
202 | IRC_SendNamesReply(); | 252 | SendServerCommand("002 " + m_nick + " :Running OpenSimVersion"); |
203 | IRC_SendChannelPrivmsg("System", "Welcome to Zork^H^H^H OpenSimulator."); | 253 | SendServerCommand("003 " + m_nick + " :This server was created over 9000 years ago"); |
204 | IRC_SendChannelPrivmsg("System", "You are in an open field west of a big white house"); | 254 | SendServerCommand("004 " + m_nick + " :opensimirc r1 aoOirw abeiIklmnoOpqrstv"); |
205 | IRC_SendChannelPrivmsg("System", "with a boarded front door."); | 255 | SendServerCommand("251 " + m_nick + " :There are 0 users and 0 services on 1 servers"); |
256 | SendServerCommand("252 " + m_nick + " 0 :operators online"); | ||
257 | SendServerCommand("253 " + m_nick + " 0 :unknown connections"); | ||
258 | SendServerCommand("254 " + m_nick + " 1 :channels formed"); | ||
259 | SendServerCommand("255 " + m_nick + " :I have 1 users, 0 services and 1 servers"); | ||
260 | SendCommand(":" + m_nick + " MODE " + m_nick + " :+i"); | ||
261 | SendCommand(":" + m_nick + " JOIN :" + IrcRegionName); | ||
262 | |||
263 | // Rename to 'Real Name' | ||
264 | SendCommand(":" + m_nick + " NICK :" + m_username.Replace(" ", "")); | ||
265 | m_nick = m_username.Replace(" ", ""); | ||
266 | |||
267 | IRC_SendReplyJoin(); | ||
268 | IRC_SendChannelPrivmsg("System", "Welcome to OpenSimulator."); | ||
269 | IRC_SendChannelPrivmsg("System", "You are in a maze of twisty little passages, all alike."); | ||
270 | IRC_SendChannelPrivmsg("System", "It is pitch black. You are likely to be eaten by a grue."); | ||
271 | |||
272 | if (OnIRCReady != null) | ||
273 | OnIRCReady(this); | ||
206 | } | 274 | } |
207 | } | 275 | } |
208 | 276 | ||
277 | private void IRC_SendReplyJoin() | ||
278 | { | ||
279 | IRC_SendReplyTopic(); | ||
280 | IRC_SendNamesReply(); | ||
281 | } | ||
282 | |||
209 | private void IRC_ProcessUser(string message) | 283 | private void IRC_ProcessUser(string message) |
210 | { | 284 | { |
211 | string[] userArgs = ExtractParameters(message); | 285 | string[] userArgs = ExtractParameters(message); |
212 | string username = userArgs[0]; | 286 | string username = userArgs[0]; |
213 | string hostname = userArgs[1]; | 287 | string hostname = userArgs[1]; |
214 | string servername = userArgs[2]; | 288 | string servername = userArgs[2]; |
215 | string realname = userArgs[3]; | 289 | string realname = userArgs[3].Replace(":", ""); |
216 | 290 | ||
217 | m_username = realname; | 291 | m_username = realname; |
218 | m_hasUser = true; | 292 | m_hasUser = true; |
@@ -221,7 +295,8 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
221 | private void IRC_ProcessNick(string message) | 295 | private void IRC_ProcessNick(string message) |
222 | { | 296 | { |
223 | string[] nickArgs = ExtractParameters(message); | 297 | string[] nickArgs = ExtractParameters(message); |
224 | string nickname = nickArgs[0]; | 298 | string nickname = nickArgs[0].Replace(":",""); |
299 | m_nick = nickname; | ||
225 | m_hasNick = true; | 300 | m_hasNick = true; |
226 | } | 301 | } |
227 | 302 | ||
@@ -243,7 +318,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
243 | msg.Sender = this; | 318 | msg.Sender = this; |
244 | msg.Channel = 0; | 319 | msg.Channel = 0; |
245 | msg.From = this.Name; | 320 | msg.From = this.Name; |
246 | msg.Message = privmsgArgs[1]; | 321 | msg.Message = privmsgArgs[1].Replace(":", ""); |
247 | msg.Position = Vector3.Zero; | 322 | msg.Position = Vector3.Zero; |
248 | msg.Scene = m_scene; | 323 | msg.Scene = m_scene; |
249 | msg.SenderObject = null; | 324 | msg.SenderObject = null; |
@@ -265,32 +340,45 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
265 | 340 | ||
266 | foreach (EntityBase user in users) | 341 | foreach (EntityBase user in users) |
267 | { | 342 | { |
268 | SendCommand("353 RPL_NAMREPLY \"" + IrcRegionName + " :+" + user.Name.Replace(" ", "")); | 343 | SendServerCommand("353 " + IrcRegionName + " :+" + user.Name.Replace(" ", "")); |
269 | } | 344 | } |
270 | SendCommand("366 RPL_ENDOFNAMES \"" + IrcRegionName + " :End of /NAMES list\""); | 345 | SendServerCommand("366 " + IrcRegionName + " :End of /NAMES list"); |
346 | } | ||
347 | |||
348 | private void IRC_SendWhoReply() | ||
349 | { | ||
350 | List<EntityBase> users = m_scene.Entities.GetAllByType<ScenePresence>(); | ||
351 | |||
352 | foreach (EntityBase user in users) | ||
353 | { | ||
354 | //:kubrick.freenode.net 352 toblerone3742 #freenode i=nalioth freenode/staff/ubuntu.member.nalioth irc.freenode.net nalioth G :0 http://www.ubuntu.com/donations | ||
355 | //:opensimircd 352 #OpenSim-Test AdamFrisbyIRC nohost.com irc.opensimulator AdamFrisbyIRC H+ :1 Adam FrisbyIRC | ||
356 | SendServerCommand("352 " + user.Name.Replace(" ", "") + " " + IrcRegionName + " nohost.com irc.opensimulator " + user.Name.Replace(" ", "") + " H+ " + ":1 " + user.Name); | ||
357 | } | ||
358 | SendServerCommand("315 " + IrcRegionName + " :End of /WHO list"); | ||
271 | } | 359 | } |
272 | 360 | ||
273 | private void IRC_SendMOTD() | 361 | private void IRC_SendMOTD() |
274 | { | 362 | { |
275 | SendCommand("375 RPL_MOTDSTART \":- OpenSimulator Message of the day -"); | 363 | SendServerCommand("375 :- OpenSimulator Message of the day -"); |
276 | SendCommand("372 RPL_MOTD \":- Hiya!"); | 364 | SendServerCommand("372 :- Hiya!"); |
277 | SendCommand("376 RPL_ENDOFMOTD \":End of /MOTD command\""); | 365 | SendServerCommand("376 :End of /MOTD command"); |
278 | } | 366 | } |
279 | 367 | ||
280 | private void IRC_SendReplyTopic() | 368 | private void IRC_SendReplyTopic() |
281 | { | 369 | { |
282 | SendCommand("332 RPL_TOPIC \"" + IrcRegionName + " :OpenSimulator IRC Server\""); | 370 | SendServerCommand("332 " + IrcRegionName + " :OpenSimulator IRC Server"); |
283 | } | 371 | } |
284 | 372 | ||
285 | private void IRC_SendReplyUsers() | 373 | private void IRC_SendReplyUsers() |
286 | { | 374 | { |
287 | List<EntityBase> users = m_scene.Entities.GetAllByType<ScenePresence>(); | 375 | List<EntityBase> users = m_scene.Entities.GetAllByType<ScenePresence>(); |
288 | 376 | ||
289 | SendCommand("392 RPL_USERSSTART \":UserID Terminal Host\""); | 377 | SendServerCommand("392 :UserID Terminal Host"); |
290 | 378 | ||
291 | if (users.Count == 0) | 379 | if (users.Count == 0) |
292 | { | 380 | { |
293 | SendCommand("395 RPL_NOUSERS \":Nobody logged in\""); | 381 | SendServerCommand("395 :Nobody logged in"); |
294 | return; | 382 | return; |
295 | } | 383 | } |
296 | 384 | ||
@@ -309,10 +397,10 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
309 | nom[i] = ' '; | 397 | nom[i] = ' '; |
310 | } | 398 | } |
311 | 399 | ||
312 | SendCommand("393 RPL_USERS \":" + nom + " " + term + " " + host + "\""); | 400 | SendServerCommand("393 :" + nom + " " + term + " " + host + ""); |
313 | } | 401 | } |
314 | 402 | ||
315 | SendCommand("394 RPL_ENDOFUSERS \":End of users\""); | 403 | SendServerCommand("394 :End of users"); |
316 | } | 404 | } |
317 | 405 | ||
318 | private static string ExtractMessage(string buffer) | 406 | private static string ExtractMessage(string buffer) |
@@ -322,7 +410,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
322 | if (pos == -1) | 410 | if (pos == -1) |
323 | return null; | 411 | return null; |
324 | 412 | ||
325 | string command = buffer.Substring(0, pos + 1); | 413 | string command = buffer.Substring(0, pos + 2); |
326 | 414 | ||
327 | return command; | 415 | return command; |
328 | } | 416 | } |
@@ -331,8 +419,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
331 | { | 419 | { |
332 | string[] msgs = msg.Split(' '); | 420 | string[] msgs = msg.Split(' '); |
333 | 421 | ||
334 | if(msgs.Length < 2) | 422 | if (msgs.Length < 2) |
423 | { | ||
424 | m_log.Warn("[IRCd] Dropped msg: " + msg); | ||
335 | return null; | 425 | return null; |
426 | } | ||
336 | 427 | ||
337 | if (msgs[0].StartsWith(":")) | 428 | if (msgs[0].StartsWith(":")) |
338 | return msgs[1]; | 429 | return msgs[1]; |
@@ -500,7 +591,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
500 | 591 | ||
501 | public uint CircuitCode | 592 | public uint CircuitCode |
502 | { | 593 | { |
503 | get { return 0; } | 594 | get { return (uint)Util.RandomClass.Next(0,int.MaxValue); } |
504 | } | 595 | } |
505 | 596 | ||
506 | public event GenericMessage OnGenericMessage; | 597 | public event GenericMessage OnGenericMessage; |
@@ -736,7 +827,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
736 | 827 | ||
737 | public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args) | 828 | public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args) |
738 | { | 829 | { |
739 | m_log.Info("[MXP ClientStack] Completing Handshake to Region"); | 830 | m_log.Info("[IRCd ClientStack] Completing Handshake to Region"); |
740 | 831 | ||
741 | if (OnRegionHandShakeReply != null) | 832 | if (OnRegionHandShakeReply != null) |
742 | { | 833 | { |
@@ -781,7 +872,8 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
781 | 872 | ||
782 | public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source, byte audible) | 873 | public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source, byte audible) |
783 | { | 874 | { |
784 | IRC_SendChannelPrivmsg(fromName, message); | 875 | if (audible > 0) |
876 | IRC_SendChannelPrivmsg(fromName, message); | ||
785 | } | 877 | } |
786 | 878 | ||
787 | private void IRC_SendChannelPrivmsg(string fromName, string message) | 879 | private void IRC_SendChannelPrivmsg(string fromName, string message) |