00001 using System;
00002 using System.Collections.Generic;
00003 using System.IO;
00004 using System.Linq;
00005 using System.Net;
00006 using System.Net.Sockets;
00007 using System.Text;
00008 using System.Text.RegularExpressions;
00009 using System.Threading;
00010
00011 namespace NicoLiveTools {
00015 public class Alert : IAlert {
00016
00018 private object m_lock = new object();
00019
00021 private ServerInfo m_serverInfo = null;
00022
00024 private Socket m_socket = null;
00025
00027 private const int m_bufferSize = 1024;
00028
00030 private byte[][] m_buffer = new byte[4][]{
00031 new byte[1024],new byte[1024],new byte[1024],new byte[1024]
00032 };
00033
00034 private int m_buffer_id = 0;
00035
00037 private ManualResetEvent m_connectSignal = new ManualResetEvent(false);
00038
00039
00040 public event EventHandler<AlertEventArgs> LiveStarted = delegate(object s, AlertEventArgs e) {
00041 };
00042
00047 public event EventHandler<DebugEventArgs> Log = delegate(object s, DebugEventArgs e) {
00048 };
00049
00054 public event EventHandler<DebugEventArgs> Recieved = delegate(object s, DebugEventArgs e) {
00055 };
00056
00060 public bool Connected {
00061 get {
00062 return (m_socket != null) && m_socket.Connected;
00063 }
00064 }
00065
00069 public Alert() {
00070 Recieved += new EventHandler<DebugEventArgs>(Alert_Recieved);
00071 }
00072
00073 ~Alert() {
00074 Disconnect();
00075 }
00076
00081 public bool Connect() {
00082 if (null != m_socket) {
00083 return false;
00084 }
00085
00086
00087 m_serverInfo = GetServerInfo();
00088 if (null == m_serverInfo || !m_serverInfo.Enabled) {
00089 return false;
00090 }
00091
00092 OnLog("Request OK : " + OfficialApi.GetAlertInfo);
00093 OnLog("↪" + m_serverInfo.Addr + ":" + m_serverInfo.Port + " , " + m_serverInfo.Thread);
00094
00095 StartRecieve();
00096
00097 return true;
00098 }
00099
00100 private bool StartRecieve() {
00101 OnLog("Listen");
00102
00103 try {
00104
00105 m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
00106
00107 m_connectSignal.Reset();
00108
00109 IAsyncResult connectResult = m_socket.BeginConnect(m_serverInfo.Addr, m_serverInfo.Port, new AsyncCallback(ConnectCallback), m_socket);
00110
00111
00112 if (!m_connectSignal.WaitOne(5000, false)) {
00113
00114 throw new Exception();
00115 }
00116
00117
00118 RecieveBuffer reciever = new RecieveBuffer(1024);
00119 m_socket.BeginReceive(reciever.Buffer, 0, 1024, SocketFlags.None, new AsyncCallback(RecieveCallback), reciever);
00120
00121
00122 byte[] senddata = Encoding.UTF8.GetBytes("<thread thread=\"" + m_serverInfo.Thread + "\" version=\"20061206\" res_from=\"-1\"/>");
00123 m_socket.BeginSend(senddata, 0, senddata.Length, SocketFlags.None, new AsyncCallback(SendCallback), m_socket);
00124 m_socket.BeginSend(new byte[]{0}, 0, 1, SocketFlags.None, new AsyncCallback(SendCallback), m_socket);
00125
00126 } catch{
00127
00128 OnLog("Socket error.");
00129
00130 Disconnect();
00131 return false;
00132 }
00133 return true;
00134 }
00135
00140 private void ConnectCallback(IAsyncResult connectResult) {
00141 Socket socket = (Socket)connectResult.AsyncState;
00142 if (socket != null) {
00143 OnLog("Connect OK.");
00144
00145 m_connectSignal.Set();
00146 }
00147 }
00148
00153 private void RecieveCallback(IAsyncResult readResult) {
00154
00155 Socket socket = m_socket;
00156
00157 RecieveBuffer reciever = readResult.AsyncState as RecieveBuffer;
00158
00159 if (null == socket || !socket.Connected) {
00160
00161 OnLog("Socket Already Disconnected.");
00162 return;
00163 }
00164 reciever.Bytes = socket.EndReceive(readResult);
00165
00166 if (reciever.Bytes > 0) {
00167 OnLog("Recieved " + reciever.Bytes + "bytes. ");
00168
00169 reciever.Analyze();
00170
00171 int i = 0;
00172 foreach (string r in reciever.LineString) {
00173 OnLog("Recieved("+ i++ +"):" + r);
00174 AlertEventArgs args = Analyze(r);
00175 OnRecieved(r);
00176 }
00177
00178 RecieveBuffer nextreciever = new RecieveBuffer(1024);
00179 socket.BeginReceive(nextreciever.Buffer, 0, 1024, SocketFlags.None, new AsyncCallback(RecieveCallback), nextreciever);
00180 } else {
00181 OnLog("Recieve Failed.");
00182 Disconnect();
00183 }
00184 }
00185
00186 private AlertEventArgs Analyze(string xml) {
00187 AlertEventArgs args = new AlertEventArgs();
00188 args.Original = xml;
00189 Match match = Regex.Match(xml, ">(.+),(.+),(.+)<");
00190 if (match.Success) {
00191 args.LiveId = match.Groups[1].Value;
00192 args.Community = match.Groups[2].Value;
00193 args.User = match.Groups[3].Value;
00194 }
00195 return args;
00196 }
00197
00202 private void SendCallback(IAsyncResult sendResult) {
00203 Socket socket = (Socket)sendResult.AsyncState;
00204 try {
00205 int sendbytes = socket.EndSend(sendResult);
00206 if (sendbytes > 0) {
00207 OnLog("Send OK.");
00208 } else {
00209 throw new ApplicationException();
00210 }
00211 } catch {
00212 OnLog("Send Error.");
00213 Disconnect();
00214 }
00215 }
00216
00220 public void Disconnect() {
00221 if (null == m_socket) {
00222 return;
00223 }
00224 try {
00225 m_socket.Shutdown(SocketShutdown.Both);
00226 } finally {
00227 m_socket.Close();
00228 m_socket = null;
00229 OnLog("Disconnected.");
00230 }
00231 }
00232
00237 protected void OnLog(string log) {
00238 Log(this, new DebugEventArgs(log));
00239 }
00240
00245 protected void OnRecieved(string recievedString) {
00246 Recieved(this, new DebugEventArgs(recievedString));
00247 }
00248
00254 protected void OnRecieved(byte[] recievedData, int bytes) {
00255 OnRecieved(Encoding.UTF8.GetString(recievedData, 0, bytes));
00256 }
00257
00263 private void Alert_Recieved(object sender, DebugEventArgs e) {
00264
00265 AlertEventArgs args = Analyze(e.Text);
00266 if (args.LiveId != "") {
00267 LiveStarted(this, args);
00268 }
00269 }
00270
00275 private ServerInfo GetServerInfo() {
00276 var result = new ServerInfo();
00277
00278 try {
00279 WebRequest request = WebRequest.Create(OfficialApi.GetAlertInfo);
00280 WebResponse response = request.GetResponse();
00281 Stream stream = response.GetResponseStream();
00282
00283 if (stream != null) {
00284 StreamReader reader = new StreamReader(stream, Encoding.UTF8);
00285 string data = reader.ReadToEnd();
00286 stream.Close();
00287
00288 Match match = Regex.Match(data, "<addr>(.+)</addr>");
00289 if (match.Success) {
00290 result.Addr = match.Groups[1].Value;
00291 }
00292 match = Regex.Match(data, "<port>(.+)</port>");
00293 if (match.Success) {
00294 result.Port = int.Parse(match.Groups[1].Value);
00295 }
00296 match = Regex.Match(data, "<thread>(.+)</thread>");
00297 if (match.Success) {
00298 result.Thread = match.Groups[1].Value;
00299 }
00300 }
00301 response.Close();
00302 } catch {
00303 return null;
00304 }
00305 return result;
00306 }
00307
00313 public static Uri GetLiveUri(int liveId) {
00314 return GetLiveUri(liveId.ToString());
00315 }
00316
00322 public static Uri GetLiveUri(string liveId) {
00323
00324 string livepart = liveId.StartsWith("lv") ? liveId : ("lv" + liveId);
00325 return new Uri("http://live.nicovideo.jp/watch/" + livepart + "?alert=2");
00326 }
00327 }
00328 }