1d9f7fe07cb424eefab0cfee9a3d64cb3fba9211
[OpenSRF.git] / src / libopensrf / transport_client.c
1 #include <opensrf/transport_client.h>
2
3 static void client_message_handler( void* client, transport_message* msg );
4
5 //int main( int argc, char** argv );
6
7 /*
8 int main( int argc, char** argv ) {
9
10         transport_message* recv;
11         transport_message* send;
12
13         transport_client* client = client_init( "spacely.georgialibraries.org", 5222 );
14
15         // try to connect, allow 15 second connect timeout 
16         if( client_connect( client, "admin", "asdfjkjk", "system", 15 ) ) {
17                 printf("Connected...\n");
18         } else { 
19                 printf( "NOT Connected...\n" ); exit(99); 
20         }
21
22         while( (recv = client_recv( client, -1 )) ) {
23
24                 if( recv->body ) {
25                         int len = strlen(recv->body);
26                         char buf[len + 20];
27                         osrf_clearbuf( buf, 0, sizeof(buf)); 
28                         sprintf( buf, "Echoing...%s", recv->body );
29                         send = message_init( buf, "Echoing Stuff", "12345", recv->sender, "" );
30                 } else {
31                         send = message_init( " * ECHOING * ", "Echoing Stuff", "12345", recv->sender, "" );
32                 }
33
34                 if( send == NULL ) { printf("something's wrong"); }
35                 client_send_message( client, send );
36                                 
37                 message_free( send );
38                 message_free( recv );
39         }
40
41         printf( "ended recv loop\n" );
42
43         return 0;
44
45 }
46 */
47
48
49 transport_client* client_init( const char* server, int port, const char* unix_path, int component ) {
50
51         if(server == NULL) return NULL;
52
53         /* build and clear the client object */
54         transport_client* client = safe_malloc( sizeof( transport_client) );
55
56         /* start with an empty message queue */
57         client->msg_q_head = NULL;
58         client->msg_q_tail = NULL;
59         
60         /* build the session */
61         client->session = init_transport( server, port, unix_path, client, component );
62
63         client->session->message_callback = client_message_handler;
64         client->error = 0;
65     client->host = strdup(server);
66
67         return client;
68 }
69
70
71 int client_connect( transport_client* client, 
72                 const char* username, const char* password, const char* resource, 
73                 int connect_timeout, enum TRANSPORT_AUTH_TYPE  auth_type ) {
74         if(client == NULL) return 0; 
75     client->xmpp_id = va_list_to_string("%s@%s/%s", username, client->host, resource);
76         return session_connect( client->session, username, 
77                         password, resource, connect_timeout, auth_type );
78 }
79
80
81 int client_disconnect( transport_client* client ) {
82         if( client == NULL ) { return 0; }
83         return session_disconnect( client->session );
84 }
85
86 int client_connected( const transport_client* client ) {
87         if(client == NULL) return 0;
88         return client->session->state_machine->connected;
89 }
90
91 int client_send_message( transport_client* client, transport_message* msg ) {
92         if(client == NULL) return 0;
93         if( client->error ) return -1;
94     msg->sender = strdup(client->xmpp_id); // free'd in message_free
95         return session_send_msg( client->session, msg );
96 }
97
98
99 transport_message* client_recv( transport_client* client, int timeout ) {
100         if( client == NULL ) { return NULL; }
101
102         int error = 0;  /* boolean */
103
104         if( NULL == client->msg_q_head ) {
105
106                 /* no messaage available?  try to get one */
107                 if( timeout == -1 ) {  /* wait potentially forever for data to arrive */
108
109                         int x;
110                         do {
111                                 if( (x = session_wait( client->session, -1 )) ) {
112                                         osrfLogDebug(OSRF_LOG_MARK, "session_wait returned failure code %d\n", x);
113                                         error = 1;
114                                         break;
115                                 }
116                         } while( client->msg_q_head == NULL );
117
118                 } else {    /* loop up to 'timeout' seconds waiting for data to arrive  */
119
120                         /* This loop assumes that a time_t is denominated in seconds -- not */
121                         /* guaranteed by Standard C, but a fair bet for Linux or UNIX       */
122
123                         time_t start = time(NULL);
124                         time_t remaining = (time_t) timeout;
125
126                         int wait_ret;
127                         do {
128                                 if( (wait_ret = session_wait( client->session, (int) remaining)) ) {
129                                         error = 1;
130                                         osrfLogDebug(OSRF_LOG_MARK,
131                                                 "session_wait returned failure code %d: setting error=1\n", wait_ret);
132                                         break;
133                                 }
134
135                                 remaining -= time(NULL) - start;
136                         } while( NULL == client->msg_q_head && remaining > 0 );
137                 }
138         }
139         
140         transport_message* msg = NULL;
141
142         if( error )
143                 client->error = 1;
144         else if( client->msg_q_head != NULL ) {
145                 /* got message(s); dequeue the oldest one */
146                 msg = client->msg_q_head;
147                 client->msg_q_head = msg->next;
148                 msg->next = NULL;  /* shouldn't be necessary; nullify for good hygiene */
149                 if( NULL == client->msg_q_head )
150                         client->msg_q_tail = NULL;
151         }
152
153         return msg;
154 }
155
156 // ---------------------------------------------------------------------------
157 // This is the message handler required by transport_session.  This handler
158 // takes an incoming message and adds it to the tail of a message queue.
159 // ---------------------------------------------------------------------------
160 static void client_message_handler( void* client, transport_message* msg ){
161
162         if(client == NULL) return;
163         if(msg == NULL) return; 
164
165         transport_client* cli = (transport_client*) client;
166
167         /* add the new message to the tail of the queue */
168         if( NULL == cli->msg_q_head )
169                 cli->msg_q_tail = cli->msg_q_head = msg;
170         else {
171                 cli->msg_q_tail->next = msg;
172                 cli->msg_q_tail = msg;
173         }
174         msg->next = NULL;
175 }
176
177
178 int client_free( transport_client* client ){
179         if(client == NULL) return 0; 
180
181         session_free( client->session );
182         transport_message* current = client->msg_q_head;
183         transport_message* next;
184
185         /* deallocate the list of messages */
186         while( current != NULL ) {
187                 next = current->next;
188                 message_free( current );
189                 current = next;
190         }
191
192     free(client->host);
193     free(client->xmpp_id);
194         free( client );
195         return 1;
196 }
197