-
Notifications
You must be signed in to change notification settings - Fork 2
/
Connection.cs
141 lines (136 loc) · 5.14 KB
/
Connection.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
using System;
using System.Net;
using System.Net.Http;
using System.Net.WebSockets;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
public class Connection
{
public enum ErorrKind
{
WrongRoomID, WebsocketClosed, WebsocketError
}
public event EventHandler<CommentEventArgs> CommentEventHandler;
public event EventHandler<ConnectionErrorArgs> ConnectionErrorHandler;
public event EventHandler<ConnectionStartArgs> ConnectionStartHandler;
bool testMode;
string baseUrl;
string baseWebSocketUri;
string roomName;
HttpClientHandler handler;
HttpClient httpClient;
CancellationTokenSource disposalTokenSource = new CancellationTokenSource();
ClientWebSocket webSocket = new ClientWebSocket();
/// <summary>
/// サーバーとの通信を担うCommetConnectionクラスコンストラクタ
/// </summary>
/// <param name="testMode">trueでローカルサーバを使用</param>
/// <param name="baseUrl">本番環境URL</param>
/// <param name="baseWebSocketUri">本番環境WebSocketURI</param>
public Connection(bool testMode, string roomName, string baseUrl, string baseWebSocketUri)
{
this.testMode = testMode;
this.roomName = roomName;
this.baseUrl = baseUrl;
this.baseWebSocketUri = baseWebSocketUri;
handler = new HttpClientHandler();
httpClient = new HttpClient(handler);
}
public void StartConnection()
{
StartWebSocket();
}
/// <summary>
/// api/loginなどをhttp://a.com/api/loginなどに変換
/// </summary>
/// <param name="path">対象のpath</param>
/// <returns></returns>
public string GetFullURL(string path)
{
if (testMode) return "http://localhost:5000/" + path;
return baseUrl + "/api/" + path;
}
private async void StartWebSocket()
{
if (webSocket.State == WebSocketState.Open) return;
if (testMode) baseWebSocketUri = "ws://localhost:5000/";
else baseWebSocketUri += "api/";
string uri = baseWebSocketUri + "v1/room/" + roomName;
await webSocket.ConnectAsync(new Uri(uri), disposalTokenSource.Token);
_ = ReceiveLoop();
if (webSocket.State == WebSocketState.Open)
ConnectionStartHandler(this, new ConnectionStartArgs(uri));
if (webSocket.State == WebSocketState.Closed)
ConnectionErrorHandler(this, new ConnectionErrorArgs(ErorrKind.WebsocketClosed, "CLOSE"));
}
private async Task ReceiveLoop()
{
var buffer = new ArraySegment<byte>(new byte[1024]);
try
{
while (!disposalTokenSource.IsCancellationRequested)
{
var received = await webSocket.ReceiveAsync(buffer, disposalTokenSource.Token);
var jsonText = System.Text.Encoding.UTF8.GetString(buffer.Array, 0, received.Count);
var eventArgs = JsonSerializer.Deserialize<CommentEventArgs>(jsonText);
CommentEventHandler(this, eventArgs);
}
}
catch (Exception e)
{
if (webSocket.State == WebSocketState.Closed){
ConnectionErrorHandler(this, new ConnectionErrorArgs(ErorrKind.WebsocketClosed, e.ToString()));
webSocket.Dispose();
webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure,String.Empty,disposalTokenSource.Token);
webSocket = null;
}
if (webSocket.State == WebSocketState.Aborted)
ConnectionErrorHandler(this, new ConnectionErrorArgs(ErorrKind.WebsocketError, e.ToString()));
return;
}
}
public async void PostComment(string text, bool isQuestion)
{
string jsonText = JsonSerializer.Serialize(new CommentEventArgs(text, isQuestion));
var content = new StringContent(jsonText, System.Text.Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync(GetFullURL($"v1/comment/{roomName}"), content);
if (response.StatusCode != System.Net.HttpStatusCode.NotFound)
{
ConnectionErrorHandler(this,
new ConnectionErrorArgs(ErorrKind.WrongRoomID,
await response.Content.ReadAsStringAsync()));
}
}
public class CommentEventArgs
{
[JsonPropertyName("comment")]
public string comment { get; set; }
[JsonPropertyName("is_question")]
public bool isQuestion { get; set; }
public CommentEventArgs(string comment, bool isQuestion)
{
this.comment = comment;
this.isQuestion = isQuestion;
}
}
public class ConnectionErrorArgs
{
public ErorrKind erorrKind { get; set; }
public string text { get; set; }
public ConnectionErrorArgs(ErorrKind erorrKind, string text)
{
this.erorrKind = erorrKind;
this.text = text;
}
}
public class ConnectionStartArgs
{
public string uri { get; set; }
public ConnectionStartArgs(string uri)
{
this.uri = uri;
}
}
}