Updated Threads
[fmail.git] / src / socketipc.cpp
blob768685668d6fc403add0fd8d295c8e361ebf0863
1 /*
2 libfmail: Socket Based IPC mechanism
4 Copyright (C) 2007 Carlos Daniel Ruvalcaba Valenzuela <clsdaniel@gmail.com>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include <stdio.h>
22 #include <string.h>
23 #include <malloc.h>
25 #include <pcrecpp.h>
27 #include <queue>
29 #include <libfmail/socket.h>
30 #include <libfmail/ipcmsg.h>
31 #include <libfmail/ipc.h>
32 #include <libfmail/socketipc.h>
34 SocketIPC::SocketIPC(Socket *s){
35 sock = s;
38 SocketIPC::SocketIPC(char *uri){
39 char *str;
40 string shost;
41 string options;
42 pcrecpp::RE re("([\\w\\d\\.]+)\\:(\\d*)[/]*(\\w*)");
44 re.PartialMatch(uri, &shost, &port, &options);
45 host = (char*)shost.c_str();
47 printf("Started socket on: %s\n", uri);
48 printf("Host: %s\nPort: %i\n", host, port);
49 sock = Socket::CreateSocket(SOCKET_INET, 0);
50 sock->setPort(port);
51 sock->setAddress(host);
52 auxsock = NULL;
55 int SocketIPC::RequestIPC(){
56 return sock->Connect();
59 int SocketIPC::ListenIPC(){
60 sock->Bind();
61 sock->Listen(10);
63 auxsock = sock->Accept();
64 return 0;
67 int SocketIPC::CloseIPC(){
68 sock->Close();
69 if (auxsock)
70 auxsock->Close();
73 /* TODO: Change to tree/graph based state machine */
74 int SocketIPC::FetchMessage2(){
75 char buffer[255], xbuff[255], tbuff[20], *msgdata;
76 int state, onParse;
77 int i, t, r, mlen, margc;
78 IPCMessage *msg;
80 state = 0;
81 onParse = 1;
83 mlen = 0;
84 margc = 0;
85 msg = NULL;
87 if (auxsock == NULL)
88 auxsock = sock;
90 while (onParse){
92 memset(buffer, 0, 255);
93 r = auxsock->Read(buffer, 255);
95 if (r < 1){
96 return 0;
97 state = -1;
98 onParse = 0;
101 for (i = 0; i < r; i++){
102 switch (state){
103 case 0:
104 if (buffer[i] == 'M')
105 state++;
106 break;
107 case 1:
108 if (buffer[i] == 'S')
109 state++;
110 break;
111 case 2:
112 if (buffer[i] == 'G')
113 state++;
114 break;
115 case 3:
116 if (buffer[i] == '['){
117 state++;
118 memset(tbuff, 0, 20);
119 t = 0;
121 break;
122 case 4:
123 if ((buffer[i] >= 48) && (buffer[i] <= 57)){
124 tbuff[t] = buffer[i];
125 t++;
126 if (t == 20)
127 state = -1;
128 }else{
129 mlen = atoi(tbuff);
130 state++;
132 break;
133 case 5:
134 if (buffer[i] == '['){
135 state++;
136 memset(tbuff, 0, 20);
137 t = 0;
139 break;
140 case 6:
141 if ((buffer[i] >= 48) && (buffer[i] <= 57)){
142 tbuff[t] = buffer[i];
143 t++;
144 if (t == 20)
145 state = -1;
146 }else{
147 margc = atoi(tbuff);
148 state++;
149 if (mlen < 255){
150 msgdata = xbuff;
151 }else{
152 msgdata = (char*)malloc(sizeof(char) * mlen + 1);
154 t = 0;
156 break;
157 case 7:
158 if (t < mlen){
159 msgdata[t] = buffer[i];
160 t++;
161 if (t == mlen){
162 msgdata[t] = 0;
163 state++;
166 break;
167 case 8:
168 msg = new IPCMessage(msgdata);
169 if (msgdata != xbuff)
170 free(msgdata);
171 state++;
173 if (margc == 0)
174 state = 20;
175 i--;
176 break;
177 case 9:
178 if (buffer[i] == 'P')
179 state++;
180 break;
181 case 10:
182 if (buffer[i] == 'A')
183 state++;
184 break;
185 case 11:
186 if (buffer[i] == 'R')
187 state++;
188 break;
189 case 12:
190 if (buffer[i] == 'A')
191 state++;
192 break;
193 case 13:
194 if (buffer[i] == 'M')
195 state++;
196 break;
197 case 14:
198 if (buffer[i] == '['){
199 state++;
200 memset(tbuff, 0, 20);
201 t = 0;
203 break;
204 case 15:
205 if ((buffer[i] >= 48) && (buffer[i] <= 57)){
206 tbuff[t] = buffer[i];
207 t++;
208 if (t == 20)
209 state = -1;
210 }else{
211 mlen = atoi(tbuff);
212 state++;
214 break;
215 case 16:
216 if (mlen < 255){
217 msgdata = xbuff;
218 }else{
219 msgdata = (char*)malloc(sizeof(char) * mlen + 1);
221 t = 0;
222 state++;
223 i--;
224 break;
225 case 17:
226 if (t < mlen){
227 msgdata[t] = buffer[i];
228 t++;
229 if (t == mlen){
230 msgdata[t] = 0;
231 state++;
232 i--;
235 break;
236 case 18:
237 msg->PushParam(msgdata);
238 if (msgdata != xbuff)
239 free(msgdata);
240 if (msg->ParamCount() == margc){
241 state++;
242 }else{
243 state = 9;
245 onParse = 0;
246 break;
247 default:
248 onParse = 0;
249 break;
254 if (state == -1){
255 if (msg)
256 delete msg;
257 return 0;
260 msgQueue.push(msg);
261 return 1;
265 int FetchMessage(){
266 char buffer[255], *param;
267 int i, j, k, s, r;
268 IPCMessage *msg;
270 memset(buffer, 0, 255);
271 r = auxsock->Read(buffer, 255);
273 if (r < 3)
274 return 0;
276 printf("buffer: %s\n", buffer);
277 m = odk_regex_match(re, buffer, 0);
279 if (m == NULL)
280 return 0;
281 printf("Regex Matched!!\n");
282 if (buffer[0] != 'M')
283 return 0;
285 param = odk_submatch_copy(buffer, m, 1);
286 i = atoi(param);
287 free(param);
289 param = odk_submatch_copy(buffer, m, 2);
290 j = atoi(param);
291 free(param);
293 memset(buffer, 0, 255);
294 r = auxsock->Read(buffer, 255);
296 if (r != i)
297 return 0;
299 msg = new IPCMessage(buffer);
300 for (i = 0; i < j; i++){
301 auxsock->Read(buffer, 255);
302 m = odk_regex_match(re, buffer, 0);
304 if ((m == NULL) || (buffer[0] != 'P'))
305 return 0;
306 param = odk_submatch_copy(buffer, m, 1);
307 k = atoi(param);
308 free(param);
310 if ((k < 1) || (k > 32000))
311 return 0;
313 param = (char*)malloc(sizeof(char) * k+1);
315 memset(param, 0, k+1);
316 s = 0;
318 while (s < k){
319 r = auxsock->Read(buffer, 255);
320 memcpy((char*)((int)param+s), buffer, r);
321 s += r;
323 msg->PushParam(param);
326 msgQueue.push(msg);
327 return 1;
331 int SocketIPC::PeekMessage(){
333 if(FetchMessage2())
334 return 1;
336 if (msgQueue.size() > 0)
337 return 1;
339 return 0;
342 /* TODO: Better memory management for IPCMessage */
343 int SocketIPC::PushMessage(IPCMessage *msg){
344 char *tmp, buffer[50];
345 int l, blen;
347 tmp = msg->GetMessageName();
348 l = strlen(tmp);
350 sprintf(buffer, "MSG[%i][%i]", l, msg->ParamCount());
351 blen = strlen(buffer);
353 sock->Write(buffer, blen);
354 sock->Write(tmp, l);
356 while(tmp = msg->PopParam()){
357 l = strlen(tmp);
359 sprintf(buffer, "PARAM[%i]", l);
360 blen = strlen(buffer);
362 sock->Write(buffer, blen);
363 sock->Write(tmp, l);
365 free(tmp);
368 return 1;
371 IPCMessage *SocketIPC::PopMessage(){
372 IPCMessage *msg;
374 msg = msgQueue.front();
375 msgQueue.pop();
377 return msg;
380 int SocketIPC::RawRead(char *buff, int size){
381 return sock->Read(buff, size);
384 int SocketIPC::RawWrite(char *buff, int size){
385 return sock->Write(buff, size);