static ChannelAuth CreateChannel( string appId, string channelId, string regionId, string endpoint, string accessKeyId, string accessKeySecret) { try { IClientProfile profile = DefaultProfile.GetProfile( regionId, accessKeyId, accessKeySecret); IAcsClient client = new DefaultAcsClient(profile); CreateChannelRequest request = new CreateChannelRequest(); request.AppId = appId; request.ChannelId = channelId; // Strongly recomment to set the RTC endpoint, // because the exception is not the "right" one if not set. // For example, if access-key-id is invalid: // 1. if endpoint is set, exception is InvalidAccessKeyId.NotFound // 2. if endpoint isn't set, exception is SDK.InvalidRegionId // that's caused by query endpoint failed. // @remark SDk will cache endpoints, however it will query endpoint for the first // time, so it's good for performance to set the endpoint. DefaultProfile.AddEndpoint(regionId, regionId, request.Product, endpoint); // Use HTTP, x3 times faster than HTTPS. request.Protocol = Aliyun.Acs.Core.Http.ProtocolType.HTTP; CreateChannelResponse response = client.GetAcsResponse(request); ChannelAuth auth = new ChannelAuth(); auth.AppId = appId; auth.ChannelId = channelId; auth.Nonce = response.Nonce; auth.Timestamp = (Int64)response.Timestamp; auth.ChannelKey = response.ChannelKey; auth.Recovered = false; auth.RequestId = response.RequestId; return(auth); } catch (Exception ex) { return(RecoverForError(ex, appId, channelId)); } }
static ChannelAuth RecoverForError(Exception ex, string appId, string channelId) { bool fatal = false; string requestId = ""; ClientException cex = ex as ClientException; if (cex != null && cex.ErrorCode != null) { requestId = cex.RequestId; string code = cex.ErrorCode; if (code == "IllegalOperationApp") { fatal = true; } else if (code.StartsWith("InvalidAccessKeyId", StringComparison.Ordinal)) { fatal = true; } else if (code == "SignatureDoesNotMatch") { fatal = true; } } if (fatal) { throw ex; } string recovered = "RCV-" + Guid.NewGuid().ToString(); System.Console.WriteLine("Recover from {0}, recovered={1}", ex.ToString(), recovered); ChannelAuth auth = new ChannelAuth(); auth.AppId = appId; auth.ChannelId = channelId; auth.Nonce = recovered; auth.Timestamp = 0; auth.ChannelKey = recovered; auth.Recovered = true; return(auth); }
static void HandleRequest(HttpListenerContext context, string appid, string accessKeyId, string accessKeySecret, string gslb, string regionId, string endpoint) { if (context.Request.Headers.Get("Origin") != "") { context.Response.Headers.Set("Access-Control-Allow-Origin", "*"); context.Response.Headers.Set("Access-Control-Allow-Methods", "GET,POST,HEAD,PUT,DELETE,OPTIONS"); context.Response.Headers.Set("Access-Control-Expose-Headers", "Server,Range,Content-Length,Content-Range"); context.Response.Headers.Set("Access-Control-Allow-Headers", "Origin,Range,Accept-Encoding,Referer,Cache-Control,X-Proxy-Authorization,X-Requested-With,Content-Type"); } if (context.Request.HttpMethod == "OPTIONS") { responseWrite(context, HttpStatusCode.OK, ""); return; } string url = context.Request.RawUrl; System.Console.WriteLine(String.Format("URL={0}", url)); if (!url.StartsWith("/app/v1/login", StringComparison.Ordinal)) { responseWrite(context, HttpStatusCode.NotFound, String.Format("Invalid url {0}", url)); return; } string channelId = context.Request.QueryString.Get("room"); string user = context.Request.QueryString.Get("user"); string channelUrl = string.Format("{0}/{1}", appid, channelId); System.Console.WriteLine(String.Format("Request channelId={0}, user={1}, appid={2}", channelId, user, appid)); try { DateTime starttime = DateTime.Now; ChannelAuth auth = null; using (Mutex locker = new Mutex()) { locker.WaitOne(); if (channels.ContainsKey(channelUrl)) { auth = channels[channelUrl]; } else { auth = CreateChannel(appid, channelId, regionId, endpoint, accessKeyId, accessKeySecret); // If recovered from error, we should never cache it, // and we should try to request again next time. if (!auth.Recovered) { channels[channelUrl] = auth; } System.Console.WriteLine(String.Format( "CreateChannel requestId={4}, cost={6}ms, channelId={0}, nonce={1}, timestamp={2}, channelKey={3}, recovered={5}", channelId, auth.Nonce, auth.Timestamp, auth.ChannelKey, auth.RequestId, auth.Recovered, DateTime.Now.Subtract(starttime).Milliseconds)); } } string userId = CreateUserId(); string token = CreateToken(channelId, auth.ChannelKey, appid, userId, auth.Nonce, auth.Timestamp); string username = String.Format( "{0}?appid={1}&channel={2}&nonce={3}×tamp={4}", userId, appid, channelId, auth.Nonce, auth.Timestamp); System.Console.WriteLine("Sign cost={4}ms, user={0}, userId={1}, token={2}, channelKey={3}", user, userId, token, auth.ChannelKey, DateTime.Now.Subtract(starttime).Milliseconds); JObject rturn = new JObject(); rturn.Add("username", username); rturn.Add("password", token); JArray rgslbs = new JArray(); rgslbs.Add(gslb); JObject rresponse = new JObject(); rresponse.Add("appid", appid); rresponse.Add("userid", userId); rresponse.Add("gslb", rgslbs); rresponse.Add("token", token); rresponse.Add("nonce", auth.Nonce); rresponse.Add("timestamp", auth.Timestamp); rresponse.Add("turn", rturn); JObject ro = new JObject(); ro.Add("code", 0); ro.Add("data", rresponse); responseWrite(context, HttpStatusCode.OK, ro.ToString()); } catch (Exception ex) { responseWrite(context, HttpStatusCode.InternalServerError, ex.Message); System.Console.WriteLine(ex.ToString()); } }