292e1435bbaeecdcafeb10348509e5e88ff36fa1
[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/logging.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
121         osrfList* msgs; /* if we're a server node we may have a pool of messages waiting to be delivered */
122
123         xmlParserCtxtPtr parserCtx; 
124         xmlDocPtr msgDoc;
125         struct __osrfChatServerStruct* parent;
126
127 };
128 typedef struct __osrfChatNodeStruct osrfChatNode;
129
130 struct __osrfChatS2SMessageStruct {
131         char* toAddr;
132         char* msgXML;
133 };
134 typedef struct __osrfChatS2SMessageStruct osrfChatS2SMessage;
135
136 struct __osrfChatServerStruct {
137         osrfHash* nodeHash; /* sometimes we need hash (remote id) lookup, sometimes we need socket id lookup */
138         osrfList* nodeList;
139         osrfList* deadNodes; /* collection of nodes to free when we get a chance */
140         socket_manager* mgr;
141         char* secret;                   /* shared S2S secret */
142         char* domain;                   /* the domain this server hosts */
143         int s2sport;
144         int port;
145 };
146
147 typedef struct __osrfChatServerStruct osrfChatServer;
148
149
150 void osrfChatCacheS2SMessage( char* toAddr, char* msgXML, osrfChatNode* snode );
151
152 osrfChatNode* osrfNewChatS2SNode( char* domain, char* remote );
153 osrfChatNode* osrfNewChatNode( int sockid, char* domain );
154 void osrfChatNodeFree( void* node );
155
156 /* @param s2sSecret The Server to server secret.  OK to leave NULL if no 
157         server to server communication is expected
158         */
159 osrfChatServer* osrfNewChatServer( char* domain, char* s2sSecret, int s2sport );
160
161 int osrfChatServerConnect( osrfChatServer* cs,  int port, int s2sport, char* listenAddr );
162
163 int osrfChatServerWait( osrfChatServer* server );
164 void osrfChatServerFree(osrfChatServer* cs);
165
166 void osrfChatHandleData( void* cs, 
167         socket_manager* mgr, int sockid, char* data, int parent_id );
168
169
170 /* removes dead nodes that have been cached due to mid-parse removals */
171 void osrfChatCleanupClients( osrfChatServer* server );
172
173
174 osrfChatNode* osrfChatAddNode( osrfChatServer* server, int sockid );
175
176
177 void osrfChatRemoveNode( osrfChatServer* server, osrfChatNode* node );
178
179 /** pushes new data into the nodes parser */
180 int osrfChatPushData( osrfChatServer* server, osrfChatNode* node, char* data );
181
182
183 void osrfChatSocketClosed( void* blob, int sockid );
184
185 /**
186   Sends msgXML to the client with remote 'toAddr'.  if we have no connection
187   to 'toAddr' and the domain for 'toAddr' is different than our hosted domain
188   we attempt to send the message to the domain found in 'toAddr'.
189   */
190 int osrfChatSend( osrfChatServer* cs, osrfChatNode* node, char* toAddr, char* fromAddr, char* msgXML );
191
192 int osrfChatSendRaw( osrfChatNode* node, char* xml );
193
194
195 void osrfChatNodeFinish( osrfChatServer* server, osrfChatNode* node );
196
197 /* initializes the negotiation of a server to server connection */
198 int osrfChatInitS2S( osrfChatServer* cs, char* remote, char* toAddr, char* msgXML );
199
200
201 void osrfChatStartStream( void* blob );
202 void osrfChatStartElement( void* blob, const xmlChar *name, const xmlChar **atts );
203 void osrfChatEndElement( void* blob, const xmlChar* name );
204 void osrfChatHandleCharacter(void* blob, const xmlChar *ch, int len);
205 void osrfChatParseError( void* blob, const char* msg, ... );
206
207 int osrfChatHandleNewConnection( osrfChatNode* node, const char* name, const xmlChar** atts );
208 int osrfChatHandleConnecting( osrfChatNode* node, const char* name, const xmlChar** atts );
209 int osrfChatHandleConnected( osrfChatNode* node, const char* name, const xmlChar** atts );
210 int osrfChatHandleS2SInit( osrfChatNode* node, const char* name, const xmlChar** atts );
211 int osrfChatHandleS2SChallenge( osrfChatNode* node, const char* name, const xmlChar** atts );
212 int osrfChatHandleS2SResponse( osrfChatNode* node, const char* name, const xmlChar** atts );
213
214 int osrfChatHandleS2SConnected( osrfChatNode* node, const char* nm, const xmlChar**atts );
215
216 void osrfChatS2SMessageFree(void* n);
217
218
219
220 /* generates a random sha1 hex key */
221 char* osrfChatMkAuthKey();
222
223 static xmlSAXHandler osrfChatSaxHandlerStruct = {
224    NULL,                                                                /* internalSubset */
225    NULL,                                                                /* isStandalone */
226    NULL,                                                                /* hasInternalSubset */
227    NULL,                                                                /* hasExternalSubset */
228    NULL,                                                                /* resolveEntity */
229    NULL,                                                                /* getEntity */
230    NULL,                                                                /* entityDecl */
231    NULL,                                                                /* notationDecl */
232    NULL,                                                                /* attributeDecl */
233    NULL,                                                                /* elementDecl */
234    NULL,                                                                /* unparsedEntityDecl */
235    NULL,                                                                /* setDocumentLocator */
236    osrfChatStartStream,                 /* startDocument */
237    NULL,                                                                /* endDocument */
238         osrfChatStartElement,           /* startElement */
239         osrfChatEndElement,                     /* endElement */
240    NULL,                                                                /* reference */
241         osrfChatHandleCharacter,        /* characters */
242    NULL,                                                                /* ignorableWhitespace */
243    NULL,                                                                /* processingInstruction */
244    NULL,                                                                /* comment */
245    osrfChatParseError,                  /* xmlParserWarning */
246    osrfChatParseError,                  /* xmlParserError */
247    NULL,                                                                /* xmlParserFatalError : unused */
248    NULL,                                                                /* getParameterEntity */
249    NULL,                                                                /* cdataBlock; */
250    NULL,                                                                /* externalSubset; */
251    1,
252    NULL,
253    NULL,                                                                /* startElementNs */
254    NULL,                                                                /* endElementNs */
255         NULL                                                            /* xmlStructuredErrorFunc */
256 };
257
258 static const xmlSAXHandlerPtr osrfChatSaxHandler = &osrfChatSaxHandlerStruct;
259
260
261 #endif
262
263