1 // Written in the D programming language.
2 
3 /**
4 This module contains a set of various useful functions for more convenient work with 9P /Styx messages.
5 
6 Copyright: LightHouse Software, 2021
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.extrautil.styxmessage;
12 
13 private {
14 	import styx2000.protoconst;
15 	
16 	import styx2000.protobj;
17 }
18 
19 /// Convenient alias
20 alias StyxMessage = StyxObject[];
21 
22 /// StyxMessage is client message ?
23 bool isTmessage(StyxMessage msg)
24 {
25 	bool isMessage = false;
26 	Type type = cast(Type) msg[1];
27 	
28 	if (type !is null)
29 	{
30 		with (STYX_MESSAGE_TYPE)
31 		{
32 			switch(type.getType) 
33 			{
34 				// version
35 				case T_VERSION:
36 					isMessage = true;
37 					break;
38 				// auth
39 				case T_AUTH:
40 					isMessage = true;
41 					break;
42 				// flush
43 				case T_FLUSH:
44 					isMessage = true;
45 					break;
46 				// attach
47 				case T_ATTACH:
48 					isMessage = true;
49 					break;
50 				// walk
51 				case T_WALK:
52 					isMessage = true;
53 					break;
54 				case T_OPEN:
55 					isMessage = true;
56 					break;
57 				// create
58 				case T_CREATE:
59 					isMessage = true;
60 					break;
61 				// read
62 				case T_READ:
63 					isMessage = true;
64 					break;
65 				// write
66 				case T_WRITE:
67 					isMessage = true;
68 					break;
69 				// clunk
70 				case T_CLUNK:
71 					isMessage = true;
72 					break;
73 				// remove
74 				case T_REMOVE:
75 					isMessage = true;
76 					break;
77 				// stat
78 				case T_STAT:
79 					isMessage = true;
80 					break;
81 				// wstat
82 				case T_WSTAT:
83 					isMessage = true;
84 					break;
85 				default:
86 					break;
87 			}
88 		}
89 	}
90 	
91 	return isMessage;
92 }
93 
94 /// StyxMessage is server message ?
95 bool isRmessage(StyxMessage msg)
96 {
97 	bool isMessage = false;
98 	Type type = cast(Type) msg[1];
99 	
100 	if (type !is null)
101 	{
102 		with (STYX_MESSAGE_TYPE)
103 		{
104 			switch(type.getType) 
105 			{
106 				// version
107 				case R_VERSION:
108 					isMessage = true;
109 					break;
110 				// auth
111 				case R_AUTH:
112 					isMessage = true;
113 					break;
114 				// flush
115 				case R_FLUSH:
116 					isMessage = true;
117 					break;
118 				// attach
119 				case R_ATTACH:
120 					isMessage = true;
121 					break;
122 				// walk
123 				case R_WALK:
124 					isMessage = true;
125 					break;
126 				case R_OPEN:
127 					isMessage = true;
128 					break;
129 				// create
130 				case R_CREATE:
131 					isMessage = true;
132 					break;
133 				// read
134 				case R_READ:
135 					isMessage = true;
136 					break;
137 				// write
138 				case R_WRITE:
139 					isMessage = true;
140 					break;
141 				// clunk
142 				case R_CLUNK:
143 					isMessage = true;
144 					break;
145 				// remove
146 				case R_REMOVE:
147 					isMessage = true;
148 					break;
149 				// stat
150 				case R_STAT:
151 					isMessage = true;
152 					break;
153 				// wstat
154 				case R_WSTAT:
155 					isMessage = true;
156 					break;
157 				// error
158 				case R_ERROR:
159 					isMessage = true;
160 					break;
161 				default:
162 					break;
163 			}
164 		}
165 	}
166 	
167 	return isMessage;
168 }
169 
170 /// StyxMessage is error message ?
171 bool isErrorMessage(StyxMessage msg)
172 {
173 	bool isMessage = false;
174 	Type type = cast(Type) msg[1];
175 	
176 	if (type !is null)
177 	{
178 		if (type.getType == STYX_MESSAGE_TYPE.R_ERROR)
179 		{
180 			isMessage = true;
181 		}
182 	}
183 	
184 	return isMessage;
185 }
186 
187 /// Create base header for 9P / Styx messages
188 auto createHeader(uint size = 0, STYX_MESSAGE_TYPE type = STYX_MESSAGE_TYPE.R_ERROR, ushort tag = STYX_NOTAG)
189 {
190 	return cast(StyxMessage) [
191 		new Size(size),
192 		new Type(type),
193 		new Tag(tag)
194 	];
195 }
196 
197 /// Create version message from client
198 auto createTmsgVersion(ushort tag = STYX_NOTAG, uint maximalSize = 8192, string vers = STYX_VERSION)
199 {
200 	return createHeader(0, STYX_MESSAGE_TYPE.T_VERSION, tag) ~ cast(StyxMessage) [
201 		new Msize(maximalSize),
202 		new Version(vers)
203 	];
204 }
205 
206 /// Create version message from server
207 auto createRmsgVersion(ushort tag = STYX_NOTAG, uint maximalSize = 8192, string vers = STYX_VERSION)
208 {
209 	return createHeader(0, STYX_MESSAGE_TYPE.R_VERSION, tag) ~ cast(StyxMessage) [
210 		new Msize(maximalSize),
211 		new Version(vers)
212 	];
213 }
214 
215 /// Create error message from server (for client this type of message does not exists)
216 auto createRmsgError(ushort tag = STYX_NOTAG, string ename = "")
217 {
218 	return createHeader(0, STYX_MESSAGE_TYPE.R_ERROR, tag) ~ cast(StyxMessage) [
219 		new Ename(ename)
220 	];
221 }
222 
223 /// Create clunk message from client
224 auto createTmsgClunk(ushort tag = STYX_NOTAG, uint fid = STYX_NOFID)
225 {
226 	return createHeader(0, STYX_MESSAGE_TYPE.T_CLUNK, tag) ~ cast(StyxMessage) [
227 		new Fid(fid)
228 	];
229 }
230 
231 /// Create clunk message from server
232 auto createRmsgClunk(ushort tag = STYX_NOTAG)
233 {
234 	return createHeader(0, STYX_MESSAGE_TYPE.R_CLUNK, tag);
235 }
236 
237 /// Create flush message from client
238 auto createTmsgFlush(ushort tag = STYX_NOTAG, ushort oldTag = STYX_NOTAG)
239 {
240 	return createHeader(0, STYX_MESSAGE_TYPE.T_FLUSH, tag) ~ cast(StyxMessage) [
241 		new OldTag(oldTag)
242 	];
243 }
244 
245 /// Create flush message from server
246 auto createRmsgFlush(ushort tag = STYX_NOTAG)
247 {
248 	return createHeader(0, STYX_MESSAGE_TYPE.R_FLUSH, tag);
249 }