Jabber WindowGram Client (JWGC)

Introduction Screenshots Installation Downloads
Documentation Browse Source Resources Project Site

Stable Version
-none-

Latest Version
beta5



Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

jconn.c

Go to the documentation of this file.
00001 /*
00002  *  This program is free software; you can redistribute it and/or modify
00003  *  it under the terms of the GNU General Public License as published by
00004  *  the Free Software Foundation; either version 2 of the License, or
00005  *  (at your option) any later version.
00006  *
00007  *  This program is distributed in the hope that it will be useful,
00008  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00009  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010  *  GNU General Public License for more details.
00011  *
00012  *  You should have received a copy of the GNU General Public License
00013  *  along with this program; if not, write to the Free Software
00014  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00015  *
00016  *  Jabber
00017  *  Copyright (C) 1998-1999 The Jabber Team http://jabber.org/
00018  *
00019  */
00020 
00021 /* $Id: jconn.c,v 1.19 2004/08/21 16:29:29 jadestorm Exp $ */
00022 
00023 #include "libjabber.h"
00024 
00025 /* local macros for launching event handlers */
00026 #define STATE_EVT(arg) if(j->on_state) { (j->on_state)(j, (arg) ); }
00027 
00028 /* prototypes of the local functions */
00029 static void startElement(void *userdata, const char *name, const char **attribs);
00030 static void endElement(void *userdata, const char *name);
00031 static void charData(void *userdata, const char *s, int slen);
00032 
00033 /*
00034  *  jab_new -- initialize a new jabber connection
00035  *
00036  *  parameters
00037  *      user -- jabber id of the user
00038  *      pass -- password of the user
00039  *
00040  *  results
00041  *      a pointer to the connection structure
00042  *      or NULL if allocations failed
00043  */
00044 jabconn 
00045 jab_new(char *user, char *pass)
00046 {
00047         xode_pool p;
00048         jabconn j;
00049 
00050         if (!user)
00051                 return (NULL);
00052 
00053         p = xode_pool_new();
00054         if (!p)
00055                 return (NULL);
00056         j = xode_pool_mallocx(p, sizeof(jabconn_struct), 0);
00057         if (!j)
00058                 return (NULL);
00059         j->p = p;
00060 
00061         j->user = jid_new(p, user);
00062         j->pass = xode_pool_strdup(p, pass);
00063         j->port = 5222;
00064 
00065         j->state = JABCONN_STATE_OFF;
00066         j->id = 1;
00067         j->fd = -1;
00068         j->dumpfd = -1;
00069         j->dumpid = NULL;
00070 #ifdef USE_SSL
00071         j->ssl = NULL;
00072         j->ssl_ctx = NULL;
00073         j->sslfd = -1;
00074 #endif /* USE_SSL */
00075 
00076         return j;
00077 }
00078 
00079 /*
00080  *  jab_delete -- free a jabber connection
00081  *
00082  *  parameters
00083  *      j -- connection
00084  *
00085  */
00086 void 
00087 jab_delete(jabconn j)
00088 {
00089         if (!j)
00090                 return;
00091 
00092         jab_stop(j);
00093         xode_pool_free(j->p);
00094 }
00095 
00096 /*
00097  *  jab_state_handler -- set callback handler for state change
00098  *
00099  *  parameters
00100  *      j -- connection
00101  *      h -- name of the handler function
00102  */
00103 void 
00104 jab_state_handler(jabconn j, jabconn_state_h h)
00105 {
00106         if (!j)
00107                 return;
00108 
00109         j->on_state = h;
00110 }
00111 
00112 /*
00113  *  jab_packet_handler -- set callback handler for incoming packets
00114  *
00115  *  parameters
00116  *      j -- connection
00117  *      h -- name of the handler function
00118  */
00119 void 
00120 jab_packet_handler(jabconn j, jabconn_packet_h h)
00121 {
00122         if (!j)
00123                 return;
00124 
00125         j->on_packet = h;
00126 }
00127 
00128 #ifdef USE_SSL
00129 void 
00130 init_prng()
00131 {
00132         if (RAND_status() == 0) {
00133                 char rand_file[256];
00134                 time_t t;
00135                 pid_t pid;
00136                 long l, seed;
00137 
00138                 t = time(NULL);
00139                 pid = getpid();
00140                 RAND_file_name((char *) &rand_file, 256);
00141                 if (rand_file != NULL) {
00142                         RAND_load_file(rand_file, 1024);
00143                 }
00144                 RAND_seed((unsigned char *) &t, sizeof(time_t));
00145                 RAND_seed((unsigned char *) &pid, sizeof(pid_t));
00146                 RAND_bytes((unsigned char *) &seed, sizeof(long));
00147                 srand48(seed);
00148                 while (RAND_status() == 0) {
00149                         l = lrand48();
00150                         RAND_seed((unsigned char *) &l, sizeof(long));
00151                 }
00152                 if (rand_file != NULL) {
00153                         RAND_write_file(rand_file);
00154                 }
00155         }
00156         return;
00157 }
00158 #endif /* USE_SSL */
00159 
00160 
00161 /*
00162  *  jab_start -- start connection
00163  *
00164  *  parameters
00165  *      j -- connection
00166  *
00167  */
00168 void 
00169 jab_start(jabconn j, int ssl)
00170 {
00171         xode x;
00172         char *t, *t2;
00173 
00174         if (!j || j->state != JABCONN_STATE_OFF)
00175                 return;
00176 
00177         j->parser = XML_ParserCreate(NULL);
00178         XML_SetUserData(j->parser, (void *) j);
00179         XML_SetElementHandler(j->parser, startElement, endElement);
00180         XML_SetCharacterDataHandler(j->parser, charData);
00181 
00182         j->fd = make_netsocket(j->port, j->user->server, NETSOCKET_CLIENT);
00183         if (j->fd < 0) {
00184                 STATE_EVT(JABCONN_STATE_OFF)
00185                         return;
00186         }
00187 
00188 #ifdef USE_SSL
00189         if (ssl && j->fd >= 0) {
00190                 SSL_library_init();
00191                 SSL_load_error_strings();
00192                 j->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
00193                 if (!j->ssl_ctx) {
00194                         STATE_EVT(JABCONN_STATE_OFF)
00195                                 return;
00196                 }
00197                 j->ssl = (SSL *)SSL_new(j->ssl_ctx);
00198                 if (!j->ssl) {
00199                         STATE_EVT(JABCONN_STATE_OFF)
00200                                 return;
00201                 }
00202                 SSL_set_fd(j->ssl, j->fd);
00203                 SSL_connect(j->ssl);
00204                 j->sslfd = SSL_get_fd(j->ssl);
00205                 if (j->sslfd < 0) {
00206                         STATE_EVT(JABCONN_STATE_OFF)
00207                                 return;
00208                 }
00209         }
00210 #endif /* USE_SSL */
00211 
00212         j->state = JABCONN_STATE_CONNECTED;
00213         STATE_EVT(JABCONN_STATE_CONNECTED)
00214         /* start stream */
00215         x = jabutil_header(NS_CLIENT, j->user->server);
00216         t = xode_to_str(x);
00217         /*
00218          * this is ugly, we can create the string here instead of
00219          * jutil_header
00220          */
00221         /* what do you think about it? -madcat */
00222         t2 = strstr(t, "/>");
00223         *t2++ = '>';
00224         *t2 = '\0';
00225         jab_send_raw(j, "<?xml version='1.0'?>");
00226         jab_send_raw(j, t);
00227         xode_free(x);
00228 
00229         jab_recv(j);
00230 
00231         j->state = JABCONN_STATE_AUTH;
00232         STATE_EVT(JABCONN_STATE_AUTH);
00233 }
00234 
00235 void
00236 jab_startup(jabconn j) {
00237         j->state = JABCONN_STATE_ON;
00238         STATE_EVT(JABCONN_STATE_ON);
00239 }
00240 
00241 /*
00242  *  jab_stop -- stop connection
00243  *
00244  *  parameters
00245  *      j -- connection
00246  */
00247 void
00248 jab_stop(jabconn j)
00249 {
00250         if (!j || j->state == JABCONN_STATE_OFF)
00251                 return;
00252 
00253         j->state = JABCONN_STATE_OFF;
00254 #ifdef USE_SSL
00255         SSL_CTX_free(j->ssl_ctx);
00256         SSL_free(j->ssl);
00257         j->ssl = NULL;
00258         j->sslfd = -1;
00259 #endif /* USE_SSL */
00260         close(j->fd);
00261         j->fd = -1;
00262         j->dumpfd = -1;
00263         j->dumpid = NULL;
00264         XML_ParserFree(j->parser);
00265 }
00266 
00267 /*
00268  *  jab_getfd -- get file descriptor of connection socket
00269  *
00270  *  parameters
00271  *      j -- connection
00272  *
00273  *  returns
00274  *      fd of the socket or -1 if socket was not connected
00275  */
00276 int
00277 jab_getfd(jabconn j)
00278 {
00279         if (j) {
00280 #ifdef USE_SSL
00281                 if (j->sslfd != -1) {
00282                         return j->sslfd;
00283                 }
00284                 else {
00285 #endif /* USE_SSL */
00286                         return j->fd;
00287 #ifdef USE_SSL
00288                 }
00289 #endif /* USE_SSL */
00290         }
00291         else {
00292                 return -1;
00293         }
00294 }
00295 
00296 /*
00297  *  jab_getjid -- get jid structure of user
00298  *
00299  *  parameters
00300  *      j -- connection
00301  */
00302 jid 
00303 jab_getjid(jabconn j)
00304 {
00305         if (j)
00306                 return (j->user);
00307         else
00308                 return NULL;
00309 }
00310 
00311 /*
00312  * jab_getsid -- get stream id This is the id of server's <stream:stream> tag
00313  * and used for digest authorization.
00314  * 
00315  * parameters j -- connection
00316  */
00317 char *
00318 jab_getsid(jabconn j)
00319 {
00320         if (j)
00321                 return (j->sid);
00322         else
00323                 return NULL;
00324 }
00325 
00326 /*
00327  *  jab_getid -- get a unique id
00328  *
00329  *  parameters
00330  *      j -- connection
00331  */
00332 char *
00333 jab_getid(jabconn j)
00334 {
00335         snprintf(j->idbuf, 8, "%d", j->id++);
00336         return &j->idbuf[0];
00337 }
00338 
00339 /*
00340  *  jab_send -- send xml data
00341  *
00342  *  parameters
00343  *      j -- connection
00344  *      x -- xode structure
00345  */
00346 void 
00347 jab_send(jabconn j, xode x)
00348 {
00349         if (j && j->state != JABCONN_STATE_OFF) {
00350                 char *buf = xode_to_str(x);
00351 #ifdef USE_SSL
00352                 if (j->sslfd == -1) {
00353 #endif /* USE_SSL */
00354                         if (buf)
00355                                 write(j->fd, buf, strlen(buf));
00356 #ifdef USE_SSL
00357                 }
00358                 else {
00359                         if (buf)
00360                                 SSL_write(j->ssl, buf, strlen(buf));
00361                 }
00362 #endif /* USE_SSL */
00363                 dprintf(dJAB, "out: %s\n", buf);
00364         }
00365 }
00366 
00367 /*
00368  *  jab_send_raw -- send a string
00369  *
00370  *  parameters
00371  *      j -- connection
00372  *      str -- xml string
00373  */
00374 void 
00375 jab_send_raw(jabconn j, const char *str)
00376 {
00377         if (j && j->state != JABCONN_STATE_OFF)
00378 #ifdef USE_SSL
00379                 if (j->sslfd == -1) {
00380 #endif /* USE_SSL */
00381                         write(j->fd, str, strlen(str));
00382 #ifdef USE_SSL
00383                 }
00384                 else {
00385                         SSL_write(j->ssl, str, strlen(str));
00386                 }
00387 #endif /* USE_SSL */
00388         dprintf(dJAB, "out: %s\n", str);
00389 }
00390 
00391 /*
00392  *  jab_recv -- read and parse incoming data
00393  *
00394  *  parameters
00395  *      j -- connection
00396  */
00397 void 
00398 jab_recv(jabconn j)
00399 {
00400         static char buf[4096];
00401         int len;
00402         int errcode;
00403 
00404         if (!j || j->state == JABCONN_STATE_OFF)
00405                 return;
00406 
00407 #ifdef USE_SSL
00408         if (j->sslfd == -1) {
00409 #endif /* USE_SSL */
00410                 len = read(j->fd, buf, sizeof(buf) - 1);
00411 #ifdef USE_SSL
00412         }
00413         else {
00414                 len = SSL_read(j->ssl, buf, sizeof(buf) - 1);
00415         }
00416 #endif /* USE_SSL */
00417         if (len > 0) {
00418                 buf[len] = '\0';
00419                 dprintf(dJAB, " in: %s\n", buf);
00420                 errcode = XML_Parse(j->parser, buf, len, 0);
00421                 dprintf(dParser, "parser index %d, line %d, col %d\n", XML_GetCurrentByteIndex(j->parser), XML_GetCurrentLineNumber(j->parser), XML_GetCurrentColumnNumber(j->parser));
00422                 if (errcode == 0) {
00423                         dprintf(dParser, "parser error %d at byte %d: %s\n", XML_GetErrorCode(j->parser), XML_GetCurrentByteIndex(j->parser), XML_ErrorString(XML_GetErrorCode(j->parser)));
00424                 }
00425                 else {
00426                         dprintf(dParser, "parser complete\n");
00427                 }
00428         }
00429         else if (len < 0) {
00430                 STATE_EVT(JABCONN_STATE_OFF);
00431                 jab_stop(j);
00432         }
00433 }
00434 
00435 /*
00436  *  jab_poll -- check socket for incoming data
00437  *
00438  *  parameters
00439  *      j -- connection
00440  *      timeout -- poll timeout
00441  */
00442 void 
00443 jab_poll(jabconn j, int timeout)
00444 {
00445         fd_set fds;
00446         FILE *selfd;
00447         struct timeval tv;
00448 
00449         if (!j || j->state == JABCONN_STATE_OFF)
00450                 return;
00451 
00452         FD_ZERO(&fds);
00453 #ifdef USE_SSL
00454         if (j->sslfd == -1) {
00455 #endif /* USE_SSL */
00456                 FD_SET(j->fd, &fds);
00457                 selfd = (FILE *) j->fd;
00458 #ifdef USE_SSL
00459         }
00460         else {
00461                 FD_SET(j->sslfd, &fds);
00462                 selfd = (FILE *) j->sslfd;
00463         }
00464 #endif /* USE_SSL */
00465 
00466 
00467         if (timeout < 0) {
00468                 if (select((int) selfd + 1, &fds, NULL, NULL, NULL) > 0)
00469                         jab_recv(j);
00470         }
00471         else {
00472                 tv.tv_sec = 0;
00473                 tv.tv_usec = timeout;
00474                 if (select((int) selfd + 1, &fds, NULL, NULL, &tv) > 0)
00475                         jab_recv(j);
00476         }
00477 }
00478 
00479 /*
00480  *  jab_auth -- authorize user
00481  *
00482  *  parameters
00483  *      j -- connection
00484  *
00485  *  returns
00486  *      id of the iq packet
00487  */
00488 char *
00489 jab_auth(jabconn j)
00490 {
00491         xode x, y, z;
00492         char *user, *id;
00493 
00494         if (!j)
00495                 return (NULL);
00496 
00497         user = j->user->user;
00498         id = jab_getid(j);
00499 
00500         x = jabutil_iqnew(JABPACKET__GET, NS_AUTH);
00501         xode_put_attrib(x, "id", "auth_1");
00502         xode_put_attrib(x, "to", j->user->server);
00503         y = xode_get_tag(x, "query");
00504 
00505         if (user) {
00506                 z = xode_insert_tag(y, "username");
00507                 xode_insert_cdata(z, user, -1);
00508         }
00509 
00510         jab_send(j, x);
00511         xode_free(x);
00512         jab_recv(j);
00513 
00514         x = jabutil_iqnew(JABPACKET__SET, NS_AUTH);
00515         xode_put_attrib(x, "id", "auth_2");
00516         xode_put_attrib(x, "to", j->user->server);
00517         y = xode_get_tag(x, "query");
00518 
00519         if (user) {
00520                 dprintf(dExecution, "Got auth user %s...\n", user);
00521                 z = xode_insert_tag(y, "username");
00522                 xode_insert_cdata(z, user, -1);
00523         }
00524 
00525         z = xode_insert_tag(y, "resource");
00526         xode_insert_cdata(z, j->user->resource, -1);
00527         dprintf(dExecution, "Got auth resource %s...\n", j->user->resource);
00528 
00529         dprintf(dExecution, "Got auth password %s...\n", j->pass);
00530         if (j->sid && j->auth_digest) {
00531                 char *hash;
00532 
00533                 dprintf(dExecution, "Got digest auth id %s...\n", j->sid);
00534                 z = xode_insert_tag(y, "digest");
00535                 hash = xode_pool_malloc(x->p,
00536                         strlen(j->sid) + strlen(j->pass) + 1);
00537                 strcpy(hash, j->sid);
00538                 strcat(hash, j->pass);
00539                 hash = (char *)j_shahash(hash);
00540                 xode_insert_cdata(z, hash, 40);
00541         }
00542         else if (j->auth_password) {
00543                 z = xode_insert_tag(y, "password");
00544                 xode_insert_cdata(z, j->pass, -1);
00545         }
00546 
00547         jab_send(j, x);
00548         xode_free(x);
00549         jab_recv(j);
00550 
00551         return id;
00552 }
00553 
00554 /*
00555  *  jab_reg -- register user
00556  *
00557  *  parameters
00558  *      j -- connection
00559  *
00560  *  returns
00561  *      id of the iq packet
00562  */
00563 char *
00564 jab_reg(jabconn j)
00565 {
00566         xode x, y, z;
00567         char *user, *id;
00568         /* UNUSED char *hash; */
00569 
00570         if (!j)
00571                 return (NULL);
00572 
00573         x = jabutil_iqnew(JABPACKET__SET, NS_REGISTER);
00574         id = jab_getid(j);
00575         xode_put_attrib(x, "id", id);
00576         y = xode_get_tag(x, "query");
00577 
00578         user = j->user->user;
00579 
00580         if (user) {
00581                 z = xode_insert_tag(y, "username");
00582                 xode_insert_cdata(z, user, -1);
00583         }
00584 
00585         z = xode_insert_tag(y, "resource");
00586         xode_insert_cdata(z, j->user->resource, -1);
00587 
00588         if (j->pass) {
00589                 z = xode_insert_tag(y, "password");
00590                 xode_insert_cdata(z, j->pass, -1);
00591         }
00592 
00593         jab_send(j, x);
00594         xode_free(x);
00595 
00596         j->state = JABCONN_STATE_AUTH;
00597         STATE_EVT(JABCONN_STATE_AUTH)
00598 
00599         return id;
00600 }
00601 
00602 
00603 /* local functions */
00604 
00605 static void 
00606 startElement(void *userdata, const char *name, const char **attribs)
00607 {
00608         xode x;
00609         jabconn j = (jabconn) userdata;
00610 
00611         if (strcmp(name, "stream:stream") == 0) {
00612                 /* special case: name == stream:stream */
00613                 /* id attrib of stream is stored for digest auth */
00614                 x = xode_new(name);
00615                 xode_put_expat_attribs(x, attribs);
00616                 j->sid = xode_get_attrib(x, "id");
00617                 xode_free(x);
00618                 dprintf(dXML, "Got stream:stream, retrieved stream id %s.\n", j->sid);
00619         }
00620 
00621         if (j->current) {
00622                 /* Append the node to the current one */
00623                 x = xode_insert_tag(j->current, name);
00624                 xode_put_expat_attribs(x, attribs);
00625 
00626                 j->current = x;
00627         }
00628         else {
00629                 x = xode_new(name);
00630                 xode_put_expat_attribs(x, attribs);
00631                 if (strcmp(name, "stream:stream") != 0) {
00632                         j->current = x;
00633                 }
00634         }
00635 }
00636 
00637 static void 
00638 endElement(void *userdata, const char *name)
00639 {
00640         jabconn j = (jabconn) userdata;
00641         xode x;
00642         jabpacket p;
00643 
00644         if (j->current == NULL) {
00645                 /* we got </stream:stream> */
00646                 STATE_EVT(JABCONN_STATE_OFF)
00647                         return;
00648         }
00649 
00650         x = xode_get_parent(j->current);
00651 
00652         if (x == NULL) {
00653                 /* it is time to fire the event */
00654                 p = jabpacket_new(j->current);
00655 
00656                 if (j->on_packet)
00657                         (j->on_packet) (j, p);
00658                 xode_free(j->current);
00659         }
00660 
00661         j->current = x;
00662 }
00663 
00664 static void 
00665 charData(void *userdata, const char *s, int slen)
00666 {
00667         jabconn j = (jabconn) userdata;
00668 
00669         if (j->current)
00670                 xode_insert_cdata(j->current, s, slen);
00671 }


Last updated at Tue Dec 18 21:07:42 PST 2007. This site and project hosted by...SourceForge.net Logo
Source Perspective by Fisheye