providing option to connect to memcache at general connect time
[OpenSRF.git] / src / jserver / osrf_chat.h
1 /*
2 Copyright (C) 2005  Georgia Public Library Service 
3 Bill Erickson <billserickson@gmail.com>
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 */
15
16 #ifndef OSRF_CHAT_H
17 #define OSRF_CHAT_H
18
19
20 /* opensrf headers */
21 #include "opensrf/utils.h"
22 #include "opensrf/osrf_hash.h"
23 #include "opensrf/osrf_list.h"
24 #include "opensrf/log.h"
25 #include "opensrf/xml_utils.h"
26 #include "opensrf/socket_bundle.h"
27 #include "opensrf/sha.h"
28 #include "opensrf/transport_message.h"
29
30 /* libxml2 headers */
31 #include <libxml/parser.h>
32 #include <libxml/tree.h>
33 #include <libxml/globals.h>
34 #include <libxml/xmlerror.h>
35
36 /* client to server XML */
37 #define OSRF_CHAT_START_STREAM "<?xml version='1.0'?><stream:stream "\
38         "xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' "\
39         "from='%s' version='1.0' id='%s'>" 
40
41 #define OSRF_CHAT_PARSE_ERROR "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' "\
42         "version='1.0'><stream:error xmlns:stream='http://etherx.jabber.org/streams'>"\
43         "<xml-not-well-formed xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>"    \
44         "<text xmlns='urn:ietf:params:xml:ns:xmpp-streams'>syntax error</text></stream:error></stream:stream>" 
45
46 #define OSRF_CHAT_LOGIN_OK "<iq xmlns='jabber:client' id='0123456789' type='result'/>"
47
48 #define OSRF_CHAT_NO_RECIPIENT "<message xmlns='jabber:client' type='error' from='%s' to='%s'>"\
49         "<error type='cancel' code='404'><item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"\
50         "</error><body>NOT ADDING BODY</body></message>"
51
52 /* ---------------------------------------------------------------------------------- */
53 /* server to server XML */
54
55 // client to server init
56 #define OSRF_CHAT_S2S_INIT "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' "\
57         "xmlns='jabber:server' xmlns:db='jabber:server:dialback'>"
58
59 // server to client challenge 
60 #define OSRF_CHAT_S2S_CHALLENGE "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' "\
61         "xmlns='jabber:server' id='%s' xmlns:db='jabber:server:dialback'>"
62
63 // client to server challenge response
64 #define OSRF_CHAT_S2S_RESPONSE "<db:result xmlns:db='jabber:server:dialback' to='%s' from='%s'>%s</db:result>"
65
66 // server to client verify
67 #define OSRF_CHAT_S2S_VERIFY_REQUEST "<db:verify xmlns:db='jabber:server:dialback' id='%s' from='%s' to='%s'>%s</db:verify>"
68
69 // client to server verify response
70 #define OSRF_CHAT_S2S_VERIFY_RESPONSE "<db:verify xmlns:db='jabber:server:dialback' type='valid' to='%s' from='%s' id='%s'/>"
71
72 //server to client final verification
73 #define OSRF_CHAT_S2S_VERIFY_FINAL "<db:result xmlns:db='jabber:server:dialback' type='valid' from='%s' to ='%s'/>"
74
75
76 /* c2s states */
77 #define OSRF_CHAT_STATE_NONE                                            0               /* blank node */
78 #define OSRF_CHAT_STATE_CONNECTING                              1               /* we have received the opening stream */
79 #define OSRF_CHAT_STATE_CONNECTED                               2               /* we have sent the OK/result message */
80
81 /* s2s states */
82 #define OSRF_CHAT_STATE_S2S_CHALLENGE                   4               /* client : waiting for the challenge */
83 #define OSRF_CHAT_STATE_S2S_RESPONSE                    5               /* server : waiting for the challenge response */
84 #define OSRF_CHAT_STATE_S2S_VERIFY                              6               /* client : waiting for verify message */
85 #define OSRF_CHAT_STATE_S2S_VERIFY_RESPONSE     7               /* server : waiting for verify response */
86 #define OSRF_CHAT_STATE_S2S_VERIFY_FINAL                8               /* client : waiting for final verify response */
87
88 /* xml parser states */
89 #define OSRF_CHAT_STATE_INMESSAGE               1
90 #define OSRF_CHAT_STATE_INIQ                            2
91 #define OSRF_CHAT_STATE_INUSERNAME              4
92 #define OSRF_CHAT_STATE_INRESOURCE              8
93 #define OSRF_CHAT_STATE_INS2SRESULT             16
94 #define OSRF_CHAT_STATE_INS2SVERIFY             32
95
96
97 struct __osrfChatNodeStruct {
98
99         int sockid;                     /* our socket id */
100
101         int type;                       /* 0 for client, 1 for server */
102
103         /* for clients this is the full JID of the client that connected to this server.
104                 for servers it's the domain (network id) of the server we're connected to */
105         char* remote;           
106
107
108         int state;                      /* for the various stages of connectivity and parsing */
109         int xmlstate;           /* what part of the message are we currently parsing */
110         int inparse;            /* true if we are currently parsing a chunk of XML.  If so, we can't 
111                                                                         free the node.  we have to cache it and free it later */
112
113         char* to;                       /* The JID where the current message is being routed */
114
115         char* domain;           /* the domain, resource, and username of our connecting entity. */ 
116         char* resource; /* for s2s nodes, resource and username will be empty . */
117         char* username;
118
119         char* authkey;          /* when doing any auth negotiation, this is the auth seed hash */
120         osrfList* msgs; /* if we're a server node we may have a pool of messages waiting to be delivered */
121
122         xmlParserCtxtPtr parserCtx; 
123         xmlDocPtr msgDoc;
124         struct __osrfChatServerStruct* parent;
125
126 };
127 typedef struct __osrfChatNodeStruct osrfChatNode;
128
129 /*
130 struct __osrfChatS2SMessageStruct {
131         char* toAddr;
132         char* msgXML;
133 };
134 typedef struct __osrfChatS2SMessageStruct osrfChatS2SMessage;
135 */
136
137 struct __osrfChatServerStruct {
138         osrfHash* nodeHash; /* sometimes we need hash (remote id) lookup, sometimes we need socket id lookup */
139         osrfList* nodeList;
140         osrfList* deadNodes; /* collection of nodes to free when we get a chance */
141         socket_manager* mgr;
142         char* secret;                   /* shared S2S secret */
143         char* domain;                   /* the domain this server hosts */
144         int s2sport;
145         int port;
146 };
147
148 typedef struct __osrfChatServerStruct osrfChatServer;
149
150
151 void osrfChatCacheS2SMessage( char* toAddr, char* msgXML, osrfChatNode* snode );
152
153 osrfChatNode* osrfNewChatS2SNode( char* domain, char* remote );
154 osrfChatNode* osrfNewChatNode( int sockid, char* domain );
155 void osrfChatNodeFree( void* node );
156
157 /* @param s2sSecret The Server to server secret.  OK to leave NULL if no 
158         server to server communication is expected
159         */
160 osrfChatServer* osrfNewChatServer( char* domain, char* s2sSecret, int s2sport );
161
162 int osrfChatServerConnect( osrfChatServer* cs,  int port, int s2sport, char* listenAddr );
163
164 int osrfChatServerWait( osrfChatServer* server );
165 void osrfChatServerFree(osrfChatServer* cs);
166
167 void osrfChatHandleData( void* cs, 
168         socket_manager* mgr, int sockid, char* data, int parent_id );
169
170
171 /* removes dead nodes that have been cached due to mid-parse removals */
172 void osrfChatCleanupClients( osrfChatServer* server );
173
174
175 osrfChatNode* osrfChatAddNode( osrfChatServer* server, int sockid );
176
177
178 void osrfChatRemoveNode( osrfChatServer* server, osrfChatNode* node );
179
180 /** pushes new data into the nodes parser */
181 int osrfChatPushData( osrfChatServer* server, osrfChatNode* node, char* data );
182
183
184 void osrfChatSocketClosed( void* blob, int sockid );
185
186 /**
187   Sends msgXML to the client with remote 'toAddr'.  if we have no connection
188   to 'toAddr' and the domain for 'toAddr' is different than our hosted domain
189   we attempt to send the message to the domain found in 'toAddr'.
190   */
191 int osrfChatSend( osrfChatServer* cs, osrfChatNode* node, char* toAddr, char* fromAddr, char* msgXML );
192
193 int osrfChatSendRaw( osrfChatNode* node, char* xml );
194
195
196 void osrfChatNodeFinish( osrfChatServer* server, osrfChatNode* node );
197
198 /* initializes the negotiation of a server to server connection */
199 int osrfChatInitS2S( osrfChatServer* cs, char* remote, char* toAddr, char* msgXML );
200
201
202 void osrfChatStartStream( void* blob );
203 void osrfChatStartElement( void* blob, const xmlChar *name, const xmlChar **atts );
204 void osrfChatEndElement( void* blob, const xmlChar* name );
205 void osrfChatHandleCharacter(void* blob, const xmlChar *ch, int len);
206 void osrfChatParseError( void* blob, const char* msg, ... );
207
208 int osrfChatHandleNewConnection( osrfChatNode* node, const char* name, const xmlChar** atts );
209 int osrfChatHandleConnecting( osrfChatNode* node, const char* name, const xmlChar** atts );
210 int osrfChatHandleConnected( osrfChatNode* node, const char* name, const xmlChar** atts );
211 int osrfChatHandleS2SInit( osrfChatNode* node, const char* name, const xmlChar** atts );
212 int osrfChatHandleS2SChallenge( osrfChatNode* node, const char* name, const xmlChar** atts );
213 int osrfChatHandleS2SResponse( osrfChatNode* node, const char* name, const xmlChar** atts );
214
215 int osrfChatHandleS2SConnected( osrfChatNode* node, const char* nm, const xmlChar**atts );
216
217 void osrfChatS2SMessageFree(void* n);
218
219
220
221 /* generates a random sha1 hex key */
222 char* osrfChatMkAuthKey();
223
224 static xmlSAXHandler osrfChatSaxHandlerStruct = {
225    NULL,                                                                /* internalSubset */
226    NULL,                                                                /* isStandalone */
227    NULL,                                                                /* hasInternalSubset */
228    NULL,                                                                /* hasExternalSubset */
229    NULL,                                                                /* resolveEntity */
230    NULL,                                                                /* getEntity */
231    NULL,                                                                /* entityDecl */
232    NULL,                                                                /* notationDecl */
233    NULL,                                                                /* attributeDecl */
234    NULL,                                                                /* elementDecl */
235    NULL,                                                                /* unparsedEntityDecl */
236    NULL,                                                                /* setDocumentLocator */
237    osrfChatStartStream,                 /* startDocument */
238    NULL,                                                                /* endDocument */
239         osrfChatStartElement,           /* startElement */
240         osrfChatEndElement,                     /* endElement */
241    NULL,                                                                /* reference */
242         osrfChatHandleCharacter,        /* characters */
243    NULL,                                                                /* ignorableWhitespace */
244    NULL,                                                                /* processingInstruction */
245    NULL,                                                                /* comment */
246    osrfChatParseError,                  /* xmlParserWarning */
247    osrfChatParseError,                  /* xmlParserError */
248    NULL,                                                                /* xmlParserFatalError : unused */
249    NULL,                                                                /* getParameterEntity */
250    NULL,                                                                /* cdataBlock; */
251    NULL,                                                                /* externalSubset; */
252    1,
253    NULL,
254    NULL,                                                                /* startElementNs */
255    NULL,                                                                /* endElementNs */
256         NULL                                                            /* xmlStructuredErrorFunc */
257 };
258
259 static const xmlSAXHandlerPtr osrfChatSaxHandler = &osrfChatSaxHandlerStruct;
260
261
262 #endif
263
264