-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathDwarfServer.cs
More file actions
executable file
·252 lines (213 loc) · 7.13 KB
/
DwarfServer.cs
File metadata and controls
executable file
·252 lines (213 loc) · 7.13 KB
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Collections.Generic;
using DwarfCMD;
using DwarfTree;
using Isis;
namespace DwarfServer
{
//TODO: Add logging of some sort to servers - Hook into Isis logging?
public class DwarfServer : DwarfCMD.DwarfCMD
{
const int DEFAULT_PORT_NUM = 9845; //!< Default port number (Isis' default + 2)
private IPHostEntry iphost; //!< IP entry point for this host
private TcpListener tcpServer; //!< TCP server listener
private TcpClient tcpClient; //!< TCP client connection
private NetworkStream networkStream; //!< Network stream for message passing
private DwarfTree.DwarfTree nodeSys; //!< Underlying node file system
/** Initializes a server with a given/default port number.
*
* @param portnum Default port number or user override.
*
*/
public DwarfServer(int portnum = DEFAULT_PORT_NUM)
{
// Set this to our actual IP (according to DNS)
this.iphost = Dns.GetHostEntry(Dns.GetHostName());
// Set the server to listen for connections on the Isis default port num + 2
this.tcpServer = new TcpListener(new IPEndPoint(iphost.AddressList[0], portnum));
this.tcpClient = null;
this.networkStream = null;
// Initialize command parsing/handling from DwarfCMD
base.dwarfCmds = new Dictionary<string, dwarfCmd>();
base.dwarfCmds["create"] = this.create;
base.dwarfCmds["rmr"] = this.delete;
base.dwarfCmds["get"] = this.getNode;
base.dwarfCmds["set"] = this.setNode;
base.dwarfCmds["stat"] = this.stat;
base.dwarfCmds["ls"] = this.getChildren;
base.dwarfCmds["sync"] = this.sync; //TODO: Eventually implement (maybe)
// Start a new DwarfTree instance for this server instance
nodeSys = DwarfTree.DwarfTree.CreateTree();
}
/** Create the node at path - CLI command is "create".
*/
private void create(string args)
{
string[] argslst = args.Split();
if(argslst.Length < 2) {
return;
}
//TODO support ACL inputs
//TODO support error messages on bad node adds
bool success = nodeSys.addNode(argslst[0], argslst[1]);
throw new NotImplementedException("create is not implemented.");
}
private void delete(string args)
{
string[] argslst = args.Split();
if(argslst.Length < 1) {
return;
}
//TODO: Enable Logging & user feedback
bool success = nodeSys.removeNode(argslst[0]);
throw new NotImplementedException("rmr is not implemented.");
}
private void getNode(string args)
{
//TODO Support watches
string[] argslst = args.Split();
if(argslst.Length < 1) {
return;
}
Dictionary<string, string> stat = nodeSys.getNode(argslst[0]);
throw new NotImplementedException("get is not implemented.");
}
private void setNode(string args)
{
string[] argslst = args.Split();
if(argslst.Length < 2) {
return;
}
bool success = nodeSys.setData(argslst[0], argslst[1]);
throw new NotImplementedException("set is not implemented.");
}
private void stat(string args)
{
//TODO Support watches
string[] argslst = args.Split();
if(argslst.Length < 1) {
return;
}
Dictionary<string, string> stats = nodeSys.getNodeInfo(argslst[0]);
throw new NotImplementedException("stat is not implemented.");
}
private void getChildren(string args)
{
//TODO Support watches
string[] argslst = args.Split();
if(argslst.Length < 1) {
return;
}
Dictionary<string, string> stats = nodeSys.getChildList(argslst[0]);
throw new NotImplementedException("ls is not implemented.");
}
private void sync(string args)
{
throw new NotImplementedException("Sync is not implemented.");
}
/** Starts the TCP server on localhost with port number.
*
*/
public void serverStart()
{
Console.WriteLine("Starting Server on " + this.tcpServer.ToString());
//TODO: What to do server is still active. No-op?
this.tcpServer.Start();
}
/** Wait for the client to connect with given timeout.
*
* Note that this initializes the network stream after connecting.
*
* @param timeout Timeout for waiting for client.
*
*/
public void waitForClient(int timeout = 0)
{
if (timeout == 0 || this.tcpServer.Pending())
{
// Attempt to get the connection immediately if
// 1) We don't care about timeouts (will block)
// 2) We have a client already trying to connect
this.tcpClient = this.tcpServer.AcceptTcpClient();
} else {
//TODO: Implement waitForClient() timeout
throw new NotImplementedException();
}
this.networkStream = this.tcpClient.GetStream();
}
/****************************************
*#######################################
* Connection/Messaging code
*#######################################
* **************************************/
/** Gets message sent from client.
*
* @return String message sent by client.
*/
public string getMessage()
{
byte[] inbuffer = new byte[256];
byte[] header = new byte[4];
this.networkStream.Read (header, 0, header.Length);
Int32 msglen = System.BitConverter.ToInt32(header, 0);
inbuffer = new byte[msglen];
this.networkStream.Read(inbuffer, 0, inbuffer.Length);
string msg = System.Text.Encoding.Unicode.GetString(inbuffer);
return msg;
}
/** Gets connection status.
*
* @return Connection status as a bool.
*/
public bool getConnectionStatus()
{
if (this.tcpClient != null)
{
return this.tcpClient.Connected;
} else {
return false;
}
}
/** Sends a string message to the client.
*
* Message contents are sent through unmolested.
* If we fail to write to the socket we assume that the
* client has disconnected and close the connection.
*
* @param msg Message to send to client
*/
public void sendMessage(string msg)
{
if (!this.getConnectionStatus())
{
Console.WriteLine("Cannot send message: disconnected");
return;
}
byte[] msgbuffer = Encoding.Unicode.GetBytes(msg); // Use UTF-8
try
{
this.networkStream.Write(BitConverter.GetBytes((Int32)msgbuffer.Length), 0, sizeof(Int32));
this.networkStream.Write(msgbuffer, 0, msgbuffer.Length);
} catch (System.IO.IOException socketExcpt) {
//TODO: Try to force client connectin closed?
Console.WriteLine("Failed to send message to server. Closing connection... ");
}
}
static void Main(string[] args)
{
DwarfServer dwarfServer = new DwarfServer();
dwarfServer.serverStart();
Console.WriteLine ("Waiting for client connection...");
dwarfServer.waitForClient();
while (true)
{
dwarfServer.parseCmd(dwarfServer.getMessage());
// dwarf_server.wait_for_client();
}
}
}
}