Imported Upstream version 0.48
[platform/upstream/libical.git] / src / libicalss / icalcstpserver.c
1 /* -*- Mode: C -*-
2     ======================================================================
3     FILE: icalcstpserver.c
4     CREATOR: ebusboom 13 Feb 01
5   
6     $Id: icalcstpserver.c,v 1.5 2008-01-02 20:15:45 dothebart Exp $
7     $Locker:  $
8     
9     (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
10     
11     This program is free software; you can redistribute it and/or modify
12     it under the terms of either: 
13     
14     The LGPL as published by the Free Software Foundation, version
15     2.1, available at: http://www.fsf.org/copyleft/lesser.html
16     
17     Or:
18     
19     The Mozilla Public License Version 1.0. You may obtain a copy of
20     the License at http://www.mozilla.org/MPL/
21
22
23     ======================================================================*/
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <libical/ical.h>
30 #include "icalcstp.h"
31 #include "icalcstpserver.h"
32 #include "pvl.h" 
33
34 #include <sys/types.h> /* For send(), others */
35 #include <sys/socket.h>  /* For send(), others. */
36 #if defined(HAVE_UNISTD_H)
37 #include <unistd.h> /* For alarm */
38 #endif
39 #include <errno.h>
40 #include <stdlib.h> /* for malloc */
41 #include <string.h>
42
43
44
45 struct icalcstps_impl {
46         int timeout;
47         icalparser *parser;
48         enum cstps_state major_state;
49         struct icalcstps_commandfp commandfp;
50 };
51
52
53
54
55 /* This state machine is a Mealy-type: actions occur on the
56    transitions, not in the states.
57    
58    Here is the state machine diagram from the CAP draft:
59
60
61         STARTTLS /
62         CAPABILITY
63        +-------+
64        |       |                       +---------------+
65        |   +-----------+ AUTHENTICATE  |               |
66        +-->| Connected |-------------->| Authenticated |
67            +-----------+               |               |
68              |                         +---------------+
69              |                              |
70              |                              |
71              |                              |
72              |                              |       +-----+ STARTTLS /
73              |                              V       |     | CAPABILITY /
74              |                         +---------------+  | IDENTIFY
75              |                         |               |<-+
76              |                         |   Identified  |<----+
77              |                +--------|               |     |
78              |                |        +---------------+     | command
79              |                |             |                | completes
80              V                |DISCONNECT   |                |
81            +--------------+   |             |SENDDATA        |
82            | Disconnected |<--+             |                |
83            +--------------+                 |                | ABORT
84                      A                      |                |
85                      |                      V                |
86                      |     DISCONNECT     +---------------+  |
87                      +--------------------|    Receive    |--+
88                                           |               |<--+
89                                           +---------------+   |
90                                                          |    | CONTINUTE
91                                                          +----+
92
93    In this implmenetation, the transition from CONNECTED to IDENTIFIED
94    is non-standard. The spec specifies that on the ATHENTICATE
95    command, the machine transitions from CONNECTED to AUTHENTICATED,
96    and then immediately goes to IDENTIFIED. This makes AUTHENTICATED a
97    useless state, so I removed it */
98
99 struct state_table {
100         enum cstps_state major_state;
101         enum icalcstp_command command;
102         void (*action)();
103         enum cstps_state next_state;
104
105 } server_state_table[] = 
106 {
107     { CONNECTED, ICAL_CAPABILITY_COMMAND , 0, CONNECTED},
108     { CONNECTED, ICAL_AUTHENTICATE_COMMAND , 0,  IDENTIFIED}, /* Non-standard */
109     { IDENTIFIED, ICAL_STARTTLS_COMMAND, 0, IDENTIFIED},
110     { IDENTIFIED, ICAL_IDENTIFY_COMMAND, 0, IDENTIFIED},
111     { IDENTIFIED, ICAL_CAPABILITY_COMMAND, 0, IDENTIFIED},
112     { IDENTIFIED, ICAL_SENDDATA_COMMAND, 0, RECEIVE},
113     { IDENTIFIED, ICAL_DISCONNECT_COMMAND, 0, DISCONNECTED},
114     { DISCONNECTED, 0, 0, 0},
115     { RECEIVE,  ICAL_DISCONNECT_COMMAND, 0, DISCONNECTED},
116     { RECEIVE,  ICAL_CONTINUE_COMMAND, 0, RECEIVE},
117     { RECEIVE,  ICAL_ABORT_COMMAND , 0, IDENTIFIED},
118     { RECEIVE,  ICAL_COMPLETE_COMMAND , 0, IDENTIFIED}
119 };
120
121
122 /**********************************************************************/
123
124
125
126 icalcstps* icalcstps_new(struct icalcstps_commandfp cfp)
127 {
128     struct icalcstps_impl* impl;
129
130     if ( ( impl = (struct icalcstps_impl*)
131            malloc(sizeof(struct icalcstps_impl))) == 0) {
132         icalerror_set_errno(ICAL_NEWFAILED_ERROR);
133         return 0;
134     }
135
136     impl->commandfp = cfp;
137     impl->timeout = 10;
138
139     return (icalcstps*)impl;
140
141 }
142
143 void icalcstps_free(icalcstps* cstp);
144
145 int icalcstps_set_timeout(icalcstps* cstp, int sec) 
146 {
147     struct icalcstps_impl *impl = (struct icalcstps_impl *) cstp;
148
149     icalerror_check_arg_rz( (cstp!=0), "cstp");
150
151     impl->timeout = sec;
152
153     return sec;
154 }
155
156 typedef struct icalcstps_response {     
157         icalrequeststatus code;
158         char caluid[1024];
159         void* result;
160 } icalcstps_response;
161
162
163 icalerrorenum prep_abort(struct icalcstps_impl* impl, char* data)
164 {
165     return ICAL_NO_ERROR;
166 }
167 icalerrorenum prep_authenticate(struct icalcstps_impl* impl, char* data)
168 {    return ICAL_NO_ERROR;
169 }
170 icalerrorenum prep_capability(struct icalcstps_impl* impl, char* data)
171 {    return ICAL_NO_ERROR;
172 }
173 icalerrorenum prep_calidexpand(struct icalcstps_impl* impl, char* data)
174 {
175     return ICAL_NO_ERROR;
176 }
177 icalerrorenum prep_continue(struct icalcstps_impl* impl, char* data)
178 {
179     return ICAL_NO_ERROR;
180 }
181 icalerrorenum prep_disconnect(struct icalcstps_impl* impl, char* data)
182 {
183     return ICAL_NO_ERROR;
184 }
185 icalerrorenum prep_identify(struct icalcstps_impl* impl, char* data)
186 {
187     return ICAL_NO_ERROR;
188 }
189 icalerrorenum prep_starttls(struct icalcstps_impl* impl, char* data)
190 {
191     return ICAL_NO_ERROR;
192 }
193 icalerrorenum prep_upnexpand(struct icalcstps_impl* impl, char* data)
194 {
195     return ICAL_NO_ERROR;
196 }
197 icalerrorenum prep_sendata(struct icalcstps_impl* impl, char* data)
198 {    return ICAL_NO_ERROR;
199 }
200
201 char* icalcstps_process_incoming(icalcstps* cstp, char* input)
202 {
203     struct icalcstps_impl *impl = (struct icalcstps_impl *) cstp;
204     char *i;
205     char *cmd_or_resp;
206     char *data;
207     char *input_cpy;
208     icalerrorenum error;
209
210     icalerror_check_arg_rz(cstp !=0,"cstp");
211     icalerror_check_arg_rz(input !=0,"input");
212
213     if ((input_cpy = (char*)strdup(input)) == 0){
214         icalerror_set_errno(ICAL_NEWFAILED_ERROR);
215         return 0;
216     }
217
218     i = (char*)strstr(" ",input_cpy);
219
220     cmd_or_resp = input_cpy;
221
222     if (i != 0){
223         *i = '\0';
224         data = ++i;
225     } else {
226         data = 0;
227     }
228
229     printf("cmd: %s\n",cmd_or_resp);
230     printf("data: %s\n",data);
231         
232     /* extract the command, look up in the state table, and dispatch
233        to the proper handler */    
234
235     if(strcmp(cmd_or_resp,"ABORT") == 0){
236         error = prep_abort(impl,data);  
237     } else if(strcmp(cmd_or_resp,"AUTHENTICATE") == 0){
238         error = prep_authenticate(impl,data);
239     } else if(strcmp(cmd_or_resp,"CAPABILITY") == 0){
240         error = prep_capability(impl,data);
241     } else if(strcmp(cmd_or_resp,"CALIDEXPAND") == 0){
242         error = prep_calidexpand(impl,data);
243     } else if(strcmp(cmd_or_resp,"CONTINUE") == 0){
244         error = prep_continue(impl,data);
245     } else if(strcmp(cmd_or_resp,"DISCONNECT") == 0){
246         error = prep_disconnect(impl,data);
247     } else if(strcmp(cmd_or_resp,"IDENTIFY") == 0){
248         error = prep_identify(impl,data);
249     } else if(strcmp(cmd_or_resp,"STARTTLS") == 0){
250         error = prep_starttls(impl,data);
251     } else if(strcmp(cmd_or_resp,"UPNEXPAND") == 0){
252         error = prep_upnexpand(impl,data);
253     } else if(strcmp(cmd_or_resp,"SENDDATA") == 0){
254         error = prep_sendata(impl,data);
255     }
256     
257     return 0;
258 }
259
260     /* Read data until we get a end of data marker */
261
262
263
264 struct icalcstps_server_stubs {
265   icalerrorenum (*abort)(icalcstps* cstp);
266   icalerrorenum (*authenticate)(icalcstps* cstp, char* mechanism, 
267                                     char* data);
268   icalerrorenum (*calidexpand)(icalcstps* cstp, char* calid);
269   icalerrorenum (*capability)(icalcstps* cstp);
270   icalerrorenum (*cont)(icalcstps* cstp, unsigned int time);
271   icalerrorenum (*identify)(icalcstps* cstp, char* id);
272   icalerrorenum (*disconnect)(icalcstps* cstp);
273   icalerrorenum (*sendata)(icalcstps* cstp, unsigned int time, 
274                                icalcomponent *comp);
275   icalerrorenum (*starttls)(icalcstps* cstp, char* command, 
276                                 char* data);
277   icalerrorenum (*upnexpand)(icalcstps* cstp, char* upn);
278   icalerrorenum (*unknown)(icalcstps* cstp, char* command, char* data);
279 };
280