2 ======================================================================
4 CREATOR: ebusboom 13 Feb 01
6 $Id: icalcstpserver.c,v 1.5 2008-01-02 20:15:45 dothebart Exp $
9 (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of either:
14 The LGPL as published by the Free Software Foundation, version
15 2.1, available at: http://www.fsf.org/copyleft/lesser.html
19 The Mozilla Public License Version 1.0. You may obtain a copy of
20 the License at http://www.mozilla.org/MPL/
23 ======================================================================*/
29 #include <libical/ical.h>
31 #include "icalcstpserver.h"
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 */
40 #include <stdlib.h> /* for malloc */
45 struct icalcstps_impl {
48 enum cstps_state major_state;
49 struct icalcstps_commandfp commandfp;
55 /* This state machine is a Mealy-type: actions occur on the
56 transitions, not in the states.
58 Here is the state machine diagram from the CAP draft:
65 | +-----------+ AUTHENTICATE | |
66 +-->| Connected |-------------->| Authenticated |
72 | | +-----+ STARTTLS /
74 | +---------------+ | IDENTIFY
76 | | Identified |<----+
78 | | +---------------+ | command
81 +--------------+ | |SENDDATA |
82 | Disconnected |<--+ | |
83 +--------------+ | | ABORT
86 | DISCONNECT +---------------+ |
87 +--------------------| Receive |--+
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 */
100 enum cstps_state major_state;
101 enum icalcstp_command command;
103 enum cstps_state next_state;
105 } server_state_table[] =
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}
122 /**********************************************************************/
126 icalcstps* icalcstps_new(struct icalcstps_commandfp cfp)
128 struct icalcstps_impl* impl;
130 if ( ( impl = (struct icalcstps_impl*)
131 malloc(sizeof(struct icalcstps_impl))) == 0) {
132 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
136 impl->commandfp = cfp;
139 return (icalcstps*)impl;
143 void icalcstps_free(icalcstps* cstp);
145 int icalcstps_set_timeout(icalcstps* cstp, int sec)
147 struct icalcstps_impl *impl = (struct icalcstps_impl *) cstp;
149 icalerror_check_arg_rz( (cstp!=0), "cstp");
156 typedef struct icalcstps_response {
157 icalrequeststatus code;
160 } icalcstps_response;
163 icalerrorenum prep_abort(struct icalcstps_impl* impl, char* data)
165 return ICAL_NO_ERROR;
167 icalerrorenum prep_authenticate(struct icalcstps_impl* impl, char* data)
168 { return ICAL_NO_ERROR;
170 icalerrorenum prep_capability(struct icalcstps_impl* impl, char* data)
171 { return ICAL_NO_ERROR;
173 icalerrorenum prep_calidexpand(struct icalcstps_impl* impl, char* data)
175 return ICAL_NO_ERROR;
177 icalerrorenum prep_continue(struct icalcstps_impl* impl, char* data)
179 return ICAL_NO_ERROR;
181 icalerrorenum prep_disconnect(struct icalcstps_impl* impl, char* data)
183 return ICAL_NO_ERROR;
185 icalerrorenum prep_identify(struct icalcstps_impl* impl, char* data)
187 return ICAL_NO_ERROR;
189 icalerrorenum prep_starttls(struct icalcstps_impl* impl, char* data)
191 return ICAL_NO_ERROR;
193 icalerrorenum prep_upnexpand(struct icalcstps_impl* impl, char* data)
195 return ICAL_NO_ERROR;
197 icalerrorenum prep_sendata(struct icalcstps_impl* impl, char* data)
198 { return ICAL_NO_ERROR;
201 char* icalcstps_process_incoming(icalcstps* cstp, char* input)
203 struct icalcstps_impl *impl = (struct icalcstps_impl *) cstp;
210 icalerror_check_arg_rz(cstp !=0,"cstp");
211 icalerror_check_arg_rz(input !=0,"input");
213 if ((input_cpy = (char*)strdup(input)) == 0){
214 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
218 i = (char*)strstr(" ",input_cpy);
220 cmd_or_resp = input_cpy;
229 printf("cmd: %s\n",cmd_or_resp);
230 printf("data: %s\n",data);
232 /* extract the command, look up in the state table, and dispatch
233 to the proper handler */
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);
260 /* Read data until we get a end of data marker */
264 struct icalcstps_server_stubs {
265 icalerrorenum (*abort)(icalcstps* cstp);
266 icalerrorenum (*authenticate)(icalcstps* cstp, char* mechanism,
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,
277 icalerrorenum (*upnexpand)(icalcstps* cstp, char* upn);
278 icalerrorenum (*unknown)(icalcstps* cstp, char* command, char* data);