1 // Written in the D programming language.
2 
3 /**
4 This module contains the base class of the 9P / Styx server for implementing your own server.
5 
6 Copyright: LightHouse Software, 2023
7 License:   $(HTTP https://github.com/aquaratixc/ESL-License, Experimental Software License 1.0).
8 Authors:   Oleg Bakharev,
9 		   Ilya Pertsev   
10 */
11 module styx2000.protosrv.basestyx;
12 
13 private {
14 	import styx2000.extrautil.casts;
15     import styx2000.extrautil.miscerrors;
16     import styx2000.extrautil.mischelpers;
17     import styx2000.extrautil.styxmessage;
18     
19     import styx2000.protoconst;
20     import styx2000.protomsg;
21     import styx2000.protobj;
22     
23     import styx2000.protosrv.baseserver;
24 }
25 
26 /// Alias for arguments of Styx handlers
27 alias StyxArguments = StyxObject[];
28 
29 
30 /// Base class for all Styx servers
31 class BaseStyxServer(uint BUFFER_SIZE, uint MAXIMAL_NUMBER_OF_CONNECTIONS, uint MAXIMAL_MESSAGE_SIZE = 8_192) : BaseServer!(BUFFER_SIZE, MAXIMAL_NUMBER_OF_CONNECTIONS)
32 {
33 	bool DEBUG_MODE = false;
34 	
35 	override ubyte[] handle(ubyte[] request)
36 	{
37 		StyxMessage response;
38 		
39 		if (request.length < 3)
40 		{
41 			response = createRmsgError(STYX_NOTAG, cast(string) STYX_ERROR_MESSAGE.ETOOSMALL);
42 		}
43 		else
44 		{
45 			/// decoded message
46 			auto msg = decode(request);
47 			/// header from message
48 			auto header = extractHeader(msg);
49 			
50 			switch (header.type)
51 			{
52 				case STYX_MESSAGE_TYPE.T_VERSION:
53 				    response = handleVersion(header.tag, msg[3..$]);
54 					break;
55 				case STYX_MESSAGE_TYPE.T_AUTH:
56 				    response = handleAuth(header.tag, msg[3..$]);
57 					break;
58 				case STYX_MESSAGE_TYPE.T_ATTACH:
59 					response = handleAttach(header.tag, msg[3..$]);
60 					break;
61 				case STYX_MESSAGE_TYPE.T_WALK:
62 					response = handleWalk(header.tag, msg[3..$]);
63 					break;
64 				case STYX_MESSAGE_TYPE.T_OPEN:
65 					response = handleOpen(header.tag, msg[3..$]);
66 					break;
67 				case STYX_MESSAGE_TYPE.T_READ:
68 					response = handleRead(header.tag, msg[3..$]);
69 					break;
70 				case STYX_MESSAGE_TYPE.T_STAT:
71 					response = handleStat(header.tag, msg[3..$]);
72 					break;
73 				case STYX_MESSAGE_TYPE.T_CLUNK:
74 					response = handleClunk(header.tag, msg[3..$]);
75 					break;
76 				case STYX_MESSAGE_TYPE.T_FLUSH:
77 					response = handleFlush(header.tag, msg[3..$]);
78 					break;
79 				case STYX_MESSAGE_TYPE.T_CREATE:
80 					response = handleCreate(header.tag, msg[3..$]);
81 					break;
82 				case STYX_MESSAGE_TYPE.T_WRITE:
83 					response = handleWrite(header.tag, msg[3..$]);
84 					break;
85 				case STYX_MESSAGE_TYPE.T_REMOVE:
86 					response = handleRemove(header.tag, msg[3..$]);
87 					break;
88 				case STYX_MESSAGE_TYPE.T_WSTAT:
89 					response = handleWstat(header.tag, msg[3..$]);
90 					break;
91 				default:
92 					response = createRmsgError(header.tag, cast(string) STYX_ERROR_MESSAGE.EINVALIDMSGTYPE);
93 					break;
94 			}
95 			
96 			/// if response length less than 3 (minimal styx m,essage length) then functional not implemented by programmer
97 			if (response.length < 3)
98 			{
99 				response = createRmsgError(header.tag, "Functional not implemented");
100 			}
101 		}
102 		
103 		if (DEBUG_MODE)
104 		{
105 			import std.stdio : writeln;
106 			
107 			if (request.length < 3)
108 			{
109 				writeln(`-> `, "Invalid 9P/Styx message");
110 				writeln(`<- `, response.toPlan9Message);
111 			}
112 			else
113 			{
114 				auto query = decode(request);
115 				
116 				writeln(`-> `, query.toPlan9Message);
117 				writeln(`<- `, response.toPlan9Message);
118 			}
119 		}
120 			
121 		return encode(fixMessageSize(response));
122 	}
123 	
124 	protected {
125 		alias StyxArguments = StyxObject[];
126 		
127 		/// 1. version message
128 		StyxMessage handleVersion(ushort tag, StyxArguments args)
129 		{
130 			return [];
131 		}
132 		
133 		/// 2. auth message
134 		StyxMessage handleAuth(ushort tag, StyxArguments args)
135 		{
136 			return [];
137 		}
138 		
139 		/// 3. attach message
140 		StyxMessage handleAttach(ushort tag, StyxArguments args)
141 		{
142 			return [];
143 		}
144 		
145 		/// 4. walk message
146 		StyxMessage handleWalk(ushort tag, StyxArguments args)
147 		{
148 			return [];
149 		}
150 		
151 		/// 5. open message
152 		StyxMessage handleOpen(ushort tag, StyxArguments args)
153 		{
154 			return [];
155 		}
156 		
157 		/// 6. read message
158 		StyxMessage handleRead(ushort tag, StyxArguments args)
159 		{
160 			return [];
161 		}
162 		
163 		/// 7. stat message
164 		StyxMessage handleStat(ushort tag, StyxArguments args)
165 		{
166 			return [];
167 		}
168 		
169 		/// 8. clunk message
170 		StyxMessage handleClunk(ushort tag, StyxArguments args)
171 		{
172 			return [];
173 		}
174 		
175 		/// 9. flush message
176 		StyxMessage handleFlush(ushort tag, StyxArguments args)
177 		{
178 			return [];
179 		}
180 		
181 		/// 10. create message
182 		StyxMessage handleCreate(ushort tag, StyxArguments args)
183 		{
184 			return [];
185 		}
186 		
187 		/// 11. write message
188 		StyxMessage handleWrite(ushort tag, StyxArguments args)
189 		{
190 			return [];
191 		}
192 		
193 		/// 12. remove message
194 		StyxMessage handleRemove(ushort tag, StyxArguments args)
195 		{
196 			return [];
197 		}
198 		
199 		/// 13. wstat message
200 		StyxMessage handleWstat(ushort tag, StyxArguments args)
201 		{
202 			return [];
203 		}
204 	}
205 }