Created
September 22, 2009 18:14
-
-
Save atsushieno/191293 to your computer and use it in GitHub Desktop.
C# lingr(2) client
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// It uses limited set of WCF features that does not such that much. | |
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Json; | |
using System.Net; | |
using System.Runtime.Serialization; | |
using System.Runtime.Serialization.Json; | |
/* | |
using System.ServiceModel; | |
using System.ServiceModel.Channels; | |
using System.ServiceModel.Description; | |
using System.ServiceModel.Dispatcher; | |
using System.ServiceModel.Web; | |
*/ | |
using System.Text; | |
using System.Xml; | |
namespace Slingr | |
{ | |
public class Test | |
{ | |
} | |
public class LingrRoom | |
{ | |
public LingrRoom (string room, string session, int counter) | |
{ | |
this.Room = room; | |
this.Session = session; | |
this.Counter = counter; | |
} | |
public string Room { get; set; } | |
public string Session { get; set; } | |
public int Counter { get; set; } | |
} | |
static class DictionaryExtension | |
{ | |
public static JsonValue Get (this JsonObject dic, string key) | |
{ | |
JsonValue value; | |
return dic.TryGetValue (key, out value) ? value : null; | |
} | |
} | |
public abstract class UnWCFLingrClientBase | |
{ | |
public static TextWriter DebugWriter = TextWriter.Null;//Console.Out; | |
protected UnWCFLingrClientBase (Uri baseUri) | |
{ | |
this.base_address = baseUri; | |
} | |
Dictionary<string,string> ToParameters (params string [] pairs) | |
{ | |
var pl = new Dictionary<string,string> (StringComparer.InvariantCultureIgnoreCase); | |
for (int i = 0; i < pairs.Length; i += 2) | |
pl [pairs [i]] = pairs [i + 1]; | |
return pl; | |
} | |
DataContractJsonSerializer sess_stat_ser = new DataContractJsonSerializer (typeof (SessionStatusResponse)); | |
protected SessionStatusResponse ToSessionStatusResponse (byte [] raw) | |
{ | |
return (SessionStatusResponse) sess_stat_ser.ReadObject (JsonReaderWriterFactory.CreateJsonReader (raw, new XmlDictionaryReaderQuotas ())); | |
} | |
Uri base_address; | |
protected byte [] RequestData (string template, params string [] parameters) | |
{ | |
var ut = new UriTemplate (template, true); | |
var pl = ToParameters (parameters); | |
var uri = ut.BindByName (base_address, pl, false); | |
DebugWriter.WriteLine ("URI: " + uri); | |
var wc = new WebClient (); | |
return wc.DownloadData (uri); | |
} | |
protected JsonObject Request (string template, params string [] parameters) | |
{ | |
string s = Encoding.UTF8.GetString (RequestData (template, parameters)); | |
DebugWriter.WriteLine (s); | |
return JsonValue.Parse (s) as JsonObject; | |
} | |
} | |
public class UnWCFLingrEventClient : UnWCFLingrClientBase, ILingrEventContract | |
{ | |
public UnWCFLingrEventClient () | |
: base (new Uri ("http://lingr.com:8080")) | |
{ | |
} | |
#region ILingrEventContract implementation | |
DataContractJsonSerializer obs_ser = new DataContractJsonSerializer (typeof (ObserveResponse)); | |
public ObserveResponse Observe (string session, int counter) | |
{ | |
var raw = RequestData ("api/event/observe?session={session}&counter={counter}", "session", session, "counter", counter.ToString ()); | |
// It is complicated: since .NET deserializer expects | |
// CLR type information ("__type":"RoomPresence:#Slingr") | |
// but the server is *not* WCF, it must be added manually. | |
// What a silly design problem. | |
var js = (JsonObject) JsonValue.Parse (Encoding.UTF8.GetString (raw)); | |
var newevts = new JsonArray (); | |
if (js ["status"] as string == "ok") { | |
foreach (JsonObject ev in (JsonArray) js ["events"]) { | |
if (ev.ContainsKey ("message")) | |
newevts.Add (new JsonObject(AddTypeInfo ("RoomMessage:#Slingr", ev))); | |
else | |
newevts.Add (new JsonObject(AddTypeInfo ("RoomPresence:#Slingr", ev))); | |
} | |
js ["events"] = newevts; | |
raw = Encoding.UTF8.GetBytes (js.ToString ()); | |
} | |
return (ObserveResponse) obs_ser.ReadObject (JsonReaderWriterFactory.CreateJsonReader (raw, new XmlDictionaryReaderQuotas ())); | |
} | |
IEnumerable<KeyValuePair<string,JsonValue>> AddTypeInfo (string type, JsonObject obj) | |
{ | |
yield return new KeyValuePair<String,JsonValue> ("__type", type); | |
foreach (var item in obj) | |
yield return item; | |
} | |
#endregion | |
} | |
public class UnWCFLingrCilent : UnWCFLingrClientBase, ILingrContract | |
{ | |
public UnWCFLingrCilent () | |
: base (new Uri ("http://lingr.com")) | |
{ | |
} | |
void FillStatus (LingrResponse r, JsonObject j) | |
{ | |
r.Status = (string) j.Get ("status"); | |
r.ErrorCode = (string) j.Get ("code"); | |
r.ErrorDetail = (string) j.Get ("detail"); | |
} | |
#region ILingrContract implementation | |
public SessionStatusResponse CreateAnonymousSession () | |
{ | |
var raw = RequestData ("api/session/create"); | |
return ToSessionStatusResponse (raw); | |
} | |
public SessionStatusResponse CreateSession (string user, string password) | |
{ | |
var raw = RequestData ("api/session/create?user={user}&password={password}", "user", user, "password", password); | |
return ToSessionStatusResponse (raw); | |
} | |
public SessionStatusResponse SetPresence (string session, string nickname, string presence) | |
{ | |
var raw = RequestData ("api/session/set_presence?session={session}&nickname={nickname}&presence={presence}", "session", session, "nickname", nickname, "presence", presence); | |
return ToSessionStatusResponse (raw); | |
} | |
public SessionStatusResponse VerifySession (string session) | |
{ | |
var raw = RequestData ("api/session/verify?session={session}", "session", session); | |
return ToSessionStatusResponse (raw); | |
} | |
EmptyResponse ToEmptyResponse (JsonObject js) | |
{ | |
var ret = new EmptyResponse (); | |
FillStatus (ret, js); | |
return ret; | |
} | |
public EmptyResponse DestroySession (string session) | |
{ | |
var js = Request ("api/session/destroy?session={session}", "session", session); | |
return ToEmptyResponse (js); | |
} | |
IEnumerable<string> AsStringEnumerable (JsonArray a) | |
{ | |
foreach (JsonPrimitive item in a) | |
yield return item; | |
} | |
public RoomsResponse GetRooms (string session) | |
{ | |
var js = Request ("api/user/get_rooms?session={session}", "session", session); | |
var ret = new RoomsResponse (); | |
FillStatus (ret, js); | |
if (ret.Status == "ok") { | |
var e = AsStringEnumerable ((JsonArray) js.Get ("rooms")); | |
ret.Rooms = e.ToArray (); | |
} | |
return ret; | |
} | |
DataContractJsonSerializer say_res_ser = new DataContractJsonSerializer (typeof (SayResponse)); | |
public SayResponse Say (string session, string room, string nickname, string text, string localId) | |
{ | |
var raw = RequestData ("api/room/say?session={session}&room={room}&nickname={nickname}&text={text}&local_id={local_id}", "session", session, "room", room, "nickname", nickname, "text", text, "local_id", localId); | |
return (SayResponse) say_res_ser.ReadObject (JsonReaderWriterFactory.CreateJsonReader (raw, new XmlDictionaryReaderQuotas ())); | |
} | |
DataContractJsonSerializer show_res_ser = new DataContractJsonSerializer (typeof (ShowResponse)); | |
public ShowResponse Show (string session, string room) | |
{ | |
var raw = RequestData ("api/room/show?session={session}&room={room}", "session", session, "room", room); | |
return (ShowResponse) show_res_ser.ReadObject (JsonReaderWriterFactory.CreateJsonReader (raw, new XmlDictionaryReaderQuotas ())); | |
} | |
DataContractJsonSerializer sub_stat_ser = new DataContractJsonSerializer (typeof (SubscriptionStatusResponse)); | |
SubscriptionStatusResponse ToSubscriptionStatus (byte [] raw) | |
{ | |
return (SubscriptionStatusResponse) sub_stat_ser.ReadObject (JsonReaderWriterFactory.CreateJsonReader (raw, new XmlDictionaryReaderQuotas ())); | |
} | |
public SubscriptionStatusResponse Subscribe (string session, string room) | |
{ | |
var raw = RequestData ("api/room/subscribe?session={session}&room={room}", "session", session, "room", room); | |
return ToSubscriptionStatus (raw); | |
} | |
public EmptyResponse Unsubscribe (string session, string room) | |
{ | |
var js = Request ("api/room/unsubscribe?session={session}&room={room}", "session", session, "room", room); | |
return ToEmptyResponse (js); | |
} | |
#endregion | |
} | |
public class LingrClient : IDisposable | |
{ | |
ILingrContract lingr; | |
ILingrEventContract lingr_event; | |
public LingrClient () | |
{ | |
/* | |
var cf = new WebChannelFactory<ILingrClient> ( | |
new CustomBinding ( | |
new WebMessageEncodingBindingElement (), | |
new HttpTransportBindingElement () { ManualAddressing = true }), | |
new Uri ("http://lingr.com")); | |
cf.Endpoint.Behaviors.Add (new LingrEndpointBehavior ()); | |
lingr = cf.CreateChannel (); | |
*/ | |
lingr = new UnWCFLingrCilent (); | |
lingr_event = new UnWCFLingrEventClient (); | |
Rooms = new List<LingrRoom> (); | |
} | |
public string Presence { get; private set; } | |
public string Session { get; private set; } | |
public string NickName { get; private set; } | |
public string PublicId { get; private set; } | |
public IList<LingrRoom> Rooms { get; private set; } | |
public void Dispose () | |
{ | |
if (lingr == null) | |
return; | |
if (Session != null) | |
DestroySession (); | |
lingr = null; | |
} | |
void CheckErrorResponse (LingrResponse res) | |
{ | |
if (res.Status != "ok") | |
throw new LingrException (res); | |
} | |
void SetSessionStatus (SessionStatusResponse res) | |
{ | |
CheckErrorResponse (res); | |
Session = res.Session; | |
Presence = res.Presence; | |
PublicId = res.PublicId; | |
NickName = res.NickName; | |
} | |
void CheckSessionExistence () | |
{ | |
if (Session == null) | |
throw new InvalidOperationException ("No session is established"); | |
} | |
// Session API wrappers | |
public void CreateAnonymousSession (string nick) | |
{ | |
var res = lingr.CreateAnonymousSession (); | |
SetSessionStatus (res); | |
this.NickName = nick; | |
} | |
public void CreateSession (string user, string password) | |
{ | |
var res = lingr.CreateSession (user, password); | |
SetSessionStatus (res); | |
} | |
public void DestroySession () | |
{ | |
CheckSessionExistence (); | |
var res = lingr.DestroySession (Session); | |
CheckErrorResponse (res); | |
Session = null; | |
Presence = null; | |
} | |
public void VerifySession () | |
{ | |
CheckSessionExistence (); | |
var res = lingr.VerifySession (Session); | |
SetSessionStatus (res); | |
} | |
public void SetPresence (bool online) | |
{ | |
CheckSessionExistence (); | |
var res = lingr.SetPresence (Ses |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment