httpsession.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  $RCSfile$
00003                              -------------------
00004     begin       : Fri Feb 15 2008
00005     copyright   : (C) 2008 by Martin Preuss
00006     email       : martin@libchipcard.de
00007 
00008  ***************************************************************************
00009  *          Please see toplevel file COPYING for license details           *
00010  ***************************************************************************/
00011 
00012 
00013 #ifdef HAVE_CONFIG_H
00014 # include <config.h>
00015 #endif
00016 
00017 
00018 #include "httpsession_p.h"
00019 #include "i18n_l.h"
00020 
00021 #include <gwenhywfar/io_socket.h>
00022 #include <gwenhywfar/io_tls.h>
00023 #include <gwenhywfar/io_http.h>
00024 #include <gwenhywfar/io_buffered.h>
00025 #include <gwenhywfar/iomanager.h>
00026 
00027 #include <gwenhywfar/misc.h>
00028 #include <gwenhywfar/debug.h>
00029 #include <gwenhywfar/gui.h>
00030 
00031 #include <assert.h>
00032 
00033 
00034 GWEN_INHERIT_FUNCTIONS(GWEN_HTTP_SESSION)
00035 
00036 
00037 
00038 GWEN_HTTP_SESSION *GWEN_HttpSession_new(const char *url,
00039                                         uint32_t guiid) {
00040   GWEN_HTTP_SESSION *sess;
00041 
00042   GWEN_NEW_OBJECT(GWEN_HTTP_SESSION, sess);
00043   assert(sess);
00044   sess->usage=1;
00045   GWEN_INHERIT_INIT(GWEN_HTTP_SESSION, sess);
00046   if (url)
00047     sess->url=GWEN_Url_fromString(url);
00048   sess->guiid=guiid;
00049 
00050   return sess;
00051 }
00052 
00053 
00054 
00055 void GWEN_HttpSession_Attach(GWEN_HTTP_SESSION *sess) {
00056   assert(sess);
00057   assert(sess->usage);
00058   sess->usage++;
00059 }
00060 
00061 
00062 
00063 void GWEN_HttpSession_free(GWEN_HTTP_SESSION *sess) {
00064   if (sess) {
00065     assert(sess->usage);
00066     if (sess->usage==1) {
00067       GWEN_INHERIT_FINI(GWEN_HTTP_SESSION, sess);
00068       GWEN_Io_Layer_free(sess->ioLayer);
00069       free(sess->httpUserAgent);
00070       free(sess->httpContentType);
00071       GWEN_FREE_OBJECT(sess);
00072     }
00073     else {
00074       sess->usage--;
00075     }
00076   }
00077 }
00078 
00079 
00080 
00081 GWEN_IO_LAYER *GWEN_HttpSession_GetIoLayer(const GWEN_HTTP_SESSION *sess) {
00082   assert(sess);
00083   assert(sess->usage);
00084 
00085   return sess->ioLayer;
00086 }
00087 
00088 
00089 
00090 uint32_t GWEN_HttpSession_GetGuiId(const GWEN_HTTP_SESSION *sess) {
00091   assert(sess);
00092   assert(sess->usage);
00093 
00094   return sess->guiid;
00095 }
00096 
00097 
00098 
00099 uint32_t GWEN_HttpSession_GetFlags(const GWEN_HTTP_SESSION *sess) {
00100   assert(sess);
00101   assert(sess->usage);
00102 
00103   return sess->flags;
00104 }
00105 
00106 
00107 
00108 void GWEN_HttpSession_SetFlags(GWEN_HTTP_SESSION *sess, uint32_t fl) {
00109   assert(sess);
00110   assert(sess->usage);
00111 
00112   sess->flags=fl;
00113 }
00114 
00115 
00116 
00117 void GWEN_HttpSession_AddFlags(GWEN_HTTP_SESSION *sess, uint32_t fl) {
00118   assert(sess);
00119   assert(sess->usage);
00120 
00121   sess->flags|=fl;
00122 }
00123 
00124 
00125 
00126 void GWEN_HttpSession_SubFlags(GWEN_HTTP_SESSION *sess, uint32_t fl) {
00127   assert(sess);
00128   assert(sess->usage);
00129 
00130   sess->flags&=~fl;
00131 }
00132 
00133 
00134 
00135 const char *GWEN_HttpSession_GetHttpUserAgent(const GWEN_HTTP_SESSION *sess) {
00136   assert(sess);
00137   assert(sess->usage);
00138 
00139   return sess->httpUserAgent;
00140 }
00141 
00142 
00143 
00144 void GWEN_HttpSession_SetHttpUserAgent(GWEN_HTTP_SESSION *sess, const char *s) {
00145   assert(sess);
00146   assert(sess->usage);
00147 
00148   free(sess->httpUserAgent);
00149   if (s)
00150     sess->httpUserAgent=strdup(s);
00151   else
00152     sess->httpUserAgent=NULL;
00153 }
00154 
00155 
00156 
00157 const char *GWEN_HttpSession_GetHttpContentType(const GWEN_HTTP_SESSION *sess) {
00158   assert(sess);
00159   assert(sess->usage);
00160 
00161   return sess->httpContentType;
00162 }
00163 
00164 
00165 
00166 void GWEN_HttpSession_SetHttpContentType(GWEN_HTTP_SESSION *sess, const char *s) {
00167   assert(sess);
00168   assert(sess->usage);
00169 
00170   free(sess->httpContentType);
00171   if (s)
00172     sess->httpContentType=strdup(s);
00173   else
00174     sess->httpContentType=NULL;
00175 }
00176 
00177 
00178 
00179 int GWEN_HttpSession_GetHttpVMajor(const GWEN_HTTP_SESSION *sess) {
00180   assert(sess);
00181   assert(sess->usage);
00182 
00183   return sess->httpVMajor;
00184 }
00185 
00186 
00187 
00188 void GWEN_HttpSession_SetHttpVMajor(GWEN_HTTP_SESSION *sess, int i) {
00189   assert(sess);
00190   assert(sess->usage);
00191 
00192   sess->httpVMajor=i;
00193 }
00194 
00195 
00196 
00197 int GWEN_HttpSession_GetHttpVMinor(const GWEN_HTTP_SESSION *sess) {
00198   assert(sess);
00199   assert(sess->usage);
00200 
00201   return sess->httpVMinor;
00202 }
00203 
00204 
00205 
00206 void GWEN_HttpSession_SetHttpVMinor(GWEN_HTTP_SESSION *sess, int i) {
00207   assert(sess);
00208   assert(sess->usage);
00209 
00210   sess->httpVMinor=i;
00211 }
00212 
00213 
00214 
00215 
00216 
00217 
00218 int GWEN_HttpSession__SetAddress(GWEN_HTTP_SESSION *sess,
00219                                  GWEN_INETADDRESS *addr,
00220                                  const char *peerAddr) {
00221   int err;
00222 
00223   err=GWEN_InetAddr_SetAddress(addr, peerAddr);
00224   if (err) {
00225     char dbgbuf[256];
00226 
00227     snprintf(dbgbuf, sizeof(dbgbuf)-1,
00228              I18N("Resolving hostname \"%s\" ..."),
00229              peerAddr);
00230     dbgbuf[sizeof(dbgbuf)-1]=0;
00231     GWEN_Gui_ProgressLog(sess->guiid,
00232                          GWEN_LoggerLevel_Notice,
00233                          dbgbuf);
00234     DBG_INFO(GWEN_LOGDOMAIN, "Resolving hostname \"%s\"",
00235              peerAddr);
00236     err=GWEN_InetAddr_SetName(addr, peerAddr);
00237     if (err) {
00238       snprintf(dbgbuf, sizeof(dbgbuf)-1,
00239                I18N("Unknown hostname \"%s\""),
00240                peerAddr);
00241       dbgbuf[sizeof(dbgbuf)-1]=0;
00242       GWEN_Gui_ProgressLog(sess->guiid,
00243                            GWEN_LoggerLevel_Error,
00244                            dbgbuf);
00245       DBG_ERROR(GWEN_LOGDOMAIN,
00246                 "Error resolving hostname \"%s\":",
00247                 peerAddr);
00248       DBG_ERROR_ERR(GWEN_LOGDOMAIN, err);
00249       return err;
00250     }
00251     else {
00252       char addrBuf[256];
00253 
00254       err=GWEN_InetAddr_GetAddress(addr, addrBuf, sizeof(addrBuf)-1);
00255       addrBuf[sizeof(addrBuf)-1]=0;
00256       if (err) {
00257         DBG_ERROR_ERR(GWEN_LOGDOMAIN, err);
00258       }
00259       else {
00260         snprintf(dbgbuf, sizeof(dbgbuf)-1,
00261                  I18N("IP address is %s"),
00262                  addrBuf);
00263         dbgbuf[sizeof(dbgbuf)-1]=0;
00264         GWEN_Gui_ProgressLog(sess->guiid,
00265                              GWEN_LoggerLevel_Notice,
00266                              dbgbuf);
00267       }
00268     }
00269   }
00270 
00271   return 0;
00272 }
00273 
00274 
00275 
00276 int GWEN_HttpSession_Init(GWEN_HTTP_SESSION *sess) {
00277   int port;
00278   GWEN_SOCKET *sk;
00279   GWEN_INETADDRESS *addr;
00280   GWEN_IO_LAYER *io;
00281   GWEN_IO_LAYER *ioBase;
00282   int rv;
00283   GWEN_DB_NODE *db;
00284   const char *s;
00285   int isHttps;
00286 
00287   /* prepare socket layer */
00288   sk=GWEN_Socket_new(GWEN_SocketTypeTCP);
00289   io=GWEN_Io_LayerSocket_new(sk);
00290 
00291   addr=GWEN_InetAddr_new(GWEN_AddressFamilyIP);
00292   rv=GWEN_HttpSession__SetAddress(sess, addr, GWEN_Url_GetServer(sess->url));
00293   if (rv<0) {
00294     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00295     GWEN_InetAddr_free(addr);
00296     return rv;
00297   }
00298 
00299   /* determine protocol */
00300   s=GWEN_Url_GetProtocol(sess->url);
00301   if (s) {
00302     if (strcasecmp(s, "http")==0) {
00303       isHttps=0;
00304     }
00305     else if (strcasecmp(s, "https")==0) {
00306       isHttps=1;
00307     }
00308     else {
00309       char dbgbuf[256];
00310 
00311       DBG_ERROR(GWEN_LOGDOMAIN, "Unknown protocol \"%s\"", s);
00312       snprintf(dbgbuf, sizeof(dbgbuf)-1,
00313                I18N("Unknown protocol \"%s\""),
00314                s);
00315       dbgbuf[sizeof(dbgbuf)-1]=0;
00316 
00317       GWEN_Gui_ProgressLog(sess->guiid,
00318                            GWEN_LoggerLevel_Error,
00319                            dbgbuf);
00320       GWEN_InetAddr_free(addr);
00321       return GWEN_ERROR_INVALID;
00322     }
00323   }
00324   else {
00325     /* default */
00326     isHttps=1;
00327   }
00328 
00329   port=GWEN_Url_GetPort(sess->url);
00330   if (port==0) {
00331     if (isHttps)
00332       port=443;
00333     else
00334       port=80;
00335   }
00336   GWEN_InetAddr_SetPort(addr, port);
00337   GWEN_Io_LayerSocket_SetPeerAddr(io, addr);
00338 
00339   /* prepare TLS layer */
00340   if (isHttps) {
00341     ioBase=io;
00342     io=GWEN_Io_LayerTls_new(ioBase);
00343     if (io==NULL) {
00344       GWEN_InetAddr_free(addr);
00345       GWEN_Io_Layer_free(ioBase);
00346       return GWEN_ERROR_GENERIC;
00347     }
00348     GWEN_Io_Layer_AddFlags(io,
00349                            GWEN_IO_LAYER_TLS_FLAGS_ALLOW_V1_CA_CRT|
00350                            GWEN_IO_LAYER_TLS_FLAGS_ADD_TRUSTED_CAS);
00351 
00352     if (sess->flags & GWEN_HTTP_SESSION_FLAGS_FORCE_SSL3)
00353       GWEN_Io_Layer_AddFlags(io, GWEN_IO_LAYER_TLS_FLAGS_FORCE_SSL_V3);
00354 
00355     GWEN_Io_LayerTls_SetRemoteHostName(io, GWEN_Url_GetServer(sess->url));
00356   }
00357 
00358   /* prepare buffered layer */
00359   ioBase=io;
00360   io=GWEN_Io_LayerBuffered_new(ioBase);
00361   if (io==NULL) {
00362     GWEN_InetAddr_free(addr);
00363     GWEN_Io_Layer_free(ioBase);
00364     return GWEN_ERROR_GENERIC;
00365   }
00366   GWEN_Io_Layer_AddFlags(io, GWEN_IO_LAYER_BUFFERED_FLAGS_DOSMODE);
00367 
00368   /* prepare HTTP layer */
00369   ioBase=io;
00370   io=GWEN_Io_LayerHttp_new(ioBase);
00371   if (io==NULL) {
00372     GWEN_InetAddr_free(addr);
00373     GWEN_Io_Layer_free(ioBase);
00374     return GWEN_ERROR_GENERIC;
00375   }
00376 
00377   /* prepare HTTP command line */
00378   db=GWEN_Io_LayerHttp_GetDbCommandOut(io);
00379   if (sess->httpVMajor) {
00380     char numbuf[32];
00381 
00382     snprintf(numbuf, sizeof(numbuf)-1, "HTTP/%d.%d",
00383              sess->httpVMajor, sess->httpVMinor);
00384     GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "protocol", numbuf);
00385   }
00386   else
00387     GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "protocol", "HTTP/1.0");
00388 
00389   if (1) {
00390     GWEN_BUFFER *pbuf;
00391 
00392     pbuf=GWEN_Buffer_new(0, 256, 0, 1);
00393     rv=GWEN_Url_toCommandString(sess->url, pbuf);
00394     if (rv) {
00395       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00396       GWEN_Buffer_free(pbuf);
00397       GWEN_InetAddr_free(addr);
00398       GWEN_Io_Layer_free(ioBase);
00399       return rv;
00400     }
00401     GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "url",
00402                          GWEN_Buffer_GetStart(pbuf));
00403     GWEN_Buffer_free(pbuf);
00404   }
00405 
00406   /* prepare HTTP out header */
00407   db=GWEN_Io_LayerHttp_GetDbHeaderOut(io);
00408   GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS,
00409                        "Host", GWEN_Url_GetServer(sess->url));
00410   GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS,
00411                        "Pragma", "no-cache");
00412   GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS,
00413                        "Cache-control", "no cache");
00414   if (sess->httpContentType)
00415     GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS,
00416                          "Content-type", sess->httpContentType);
00417 
00418   if (sess->httpUserAgent)
00419     GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS,
00420                          "User-Agent", sess->httpUserAgent);
00421   GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "Connection", "close");
00422   GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "Content-length", 0);
00423 
00424   /* now register the layer */
00425   rv=GWEN_Io_Manager_RegisterLayer(io);
00426   if (rv<0) {
00427     DBG_INFO(GWEN_LOGDOMAIN, "Could not register io layer (%d)", rv);
00428     GWEN_InetAddr_free(addr);
00429     GWEN_Io_Layer_free(io);
00430     return 0;
00431   }
00432 
00433   sess->ioLayer=io;
00434   GWEN_InetAddr_free(addr);
00435   return 0;
00436 }
00437 
00438 
00439 
00440 int GWEN_HttpSession_Fini(GWEN_HTTP_SESSION *sess) {
00441   assert(sess);
00442   assert(sess->usage);
00443 
00444   GWEN_Io_Layer_free(sess->ioLayer);
00445   sess->ioLayer=0;
00446   return 0;
00447 }
00448 
00449 
00450 
00451 int GWEN_HttpSession_SendPacket(GWEN_HTTP_SESSION *sess,
00452                                 const char *httpCommand,
00453                                 const uint8_t *buf, uint32_t blen,
00454                                 int timeout) {
00455   int rv;
00456 
00457   assert(sess);
00458   assert(sess->usage);
00459 
00460   /* first connect to server */
00461   GWEN_Gui_ProgressLog(sess->guiid,
00462                        GWEN_LoggerLevel_Notice,
00463                        I18N("Connecting to server..."));
00464   rv=GWEN_Io_Layer_ConnectRecursively(sess->ioLayer, NULL, 0,
00465                                       sess->guiid, 30000);
00466   if (rv==GWEN_ERROR_SSL) {
00467     GWEN_IO_LAYER *ioTls;
00468 
00469     /* try again with alternated SSLv3 flag */
00470     DBG_NOTICE(GWEN_LOGDOMAIN,
00471                "SSL-Error connecting (%d), retrying", rv);
00472     GWEN_Io_Layer_DisconnectRecursively(sess->ioLayer, NULL,
00473                                         GWEN_IO_REQUEST_FLAGS_FORCE,
00474                                         sess->guiid, 2000);
00475     ioTls=GWEN_Io_Layer_FindBaseLayerByType(sess->ioLayer,
00476                                             GWEN_IO_LAYER_TLS_TYPE);
00477     assert(ioTls);
00478 
00479     if (sess->flags & GWEN_HTTP_SESSION_FLAGS_FORCE_SSL3) {
00480       DBG_INFO(GWEN_LOGDOMAIN, "Retrying to connect (non-SSLv3)");
00481       GWEN_Gui_ProgressLog(sess->guiid,
00482                            GWEN_LoggerLevel_Info,
00483                            I18N("Retrying to connect (non-SSLv3)"));
00484       GWEN_Io_Layer_SubFlags(ioTls, GWEN_IO_LAYER_TLS_FLAGS_FORCE_SSL_V3);
00485       rv=GWEN_Io_Layer_ConnectRecursively(sess->ioLayer, NULL, 0,
00486                                           sess->guiid, 30000);
00487       if (rv==0) {
00488         GWEN_HttpSession_SubFlags(sess, GWEN_HTTP_SESSION_FLAGS_FORCE_SSL3);
00489       }
00490     }
00491     else {
00492       DBG_INFO(GWEN_LOGDOMAIN, "Retrying to connect (SSLv3)");
00493       GWEN_Gui_ProgressLog(sess->guiid,
00494                            GWEN_LoggerLevel_Info,
00495                            I18N("Retrying to connect (SSLv3)"));
00496       GWEN_Io_Layer_AddFlags(ioTls, GWEN_IO_LAYER_TLS_FLAGS_FORCE_SSL_V3);
00497       rv=GWEN_Io_Layer_ConnectRecursively(sess->ioLayer, NULL, 0,
00498                                           sess->guiid, 30000);
00499       if (rv==0) {
00500         GWEN_HttpSession_AddFlags(sess, GWEN_HTTP_SESSION_FLAGS_FORCE_SSL3);
00501       }
00502     }
00503   }
00504 
00505   if (rv<0) {
00506     DBG_INFO(GWEN_LOGDOMAIN, "Could not connect to server (%d)", rv);
00507     GWEN_Gui_ProgressLog(sess->guiid,
00508                          GWEN_LoggerLevel_Error,
00509                          I18N("Could not connect to server"));
00510     GWEN_Io_Layer_DisconnectRecursively(sess->ioLayer, NULL,
00511                                         GWEN_IO_REQUEST_FLAGS_FORCE,
00512                                         sess->guiid, 2000);
00513     return rv;
00514   }
00515   else {
00516     GWEN_DB_NODE *db;
00517 
00518     GWEN_Gui_ProgressLog(sess->guiid,
00519                          GWEN_LoggerLevel_Info,
00520                          I18N("Connected."));
00521 
00522     /* set command */
00523     db=GWEN_Io_LayerHttp_GetDbCommandOut(sess->ioLayer);
00524     GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS,
00525                          "command",
00526                          httpCommand);
00527 
00528     /* set content length */
00529     db=GWEN_Io_LayerHttp_GetDbHeaderOut(sess->ioLayer);
00530     GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS,
00531                         "Content-length", blen);
00532 
00533     GWEN_Gui_ProgressLog(sess->guiid,
00534                          GWEN_LoggerLevel_Info,
00535                          I18N("Sending message..."));
00536     rv=GWEN_Io_Layer_WriteBytes(sess->ioLayer,
00537                                 buf, blen,
00538                                 GWEN_IO_REQUEST_FLAGS_PACKETBEGIN |
00539                                 GWEN_IO_REQUEST_FLAGS_PACKETEND |
00540                                 GWEN_IO_REQUEST_FLAGS_FLUSH,
00541                                 sess->guiid, timeout);
00542     if (rv<0) {
00543       DBG_INFO(GWEN_LOGDOMAIN, "Could not send message (%d)", rv);
00544       GWEN_Gui_ProgressLog(sess->guiid,
00545                            GWEN_LoggerLevel_Error,
00546                            I18N("Could not send message"));
00547       GWEN_Io_Layer_DisconnectRecursively(sess->ioLayer, NULL,
00548                                           GWEN_IO_REQUEST_FLAGS_FORCE,
00549                                           sess->guiid, 2000);
00550       return rv;
00551     }
00552 
00553     DBG_INFO(GWEN_LOGDOMAIN, "Message sent.");
00554     GWEN_Gui_ProgressLog(sess->guiid,
00555                          GWEN_LoggerLevel_Info,
00556                          I18N("Message sent."));
00557     return 0;
00558   }
00559 }
00560 
00561 
00562 
00563 int GWEN_HttpSession__RecvPacket(GWEN_HTTP_SESSION *sess,
00564                                  GWEN_BUFFER *buf, GWEN_UNUSED int timeout) {
00565   int rv;
00566   GWEN_DB_NODE *db;
00567   int code;
00568 
00569   assert(sess);
00570   assert(sess->usage);
00571 
00572   /* recv packet (this reads the HTTP body) */
00573   rv=GWEN_Io_Layer_ReadPacketToBuffer(sess->ioLayer, buf, 0,
00574                                       sess->guiid, 30000);
00575   if (rv<0) {
00576     if (GWEN_Buffer_GetUsedBytes(buf)) {
00577       /* data received, check for common error codes */
00578       if (rv==GWEN_ERROR_EOF || (rv==GWEN_ERROR_IO)) {
00579         DBG_INFO(GWEN_LOGDOMAIN,
00580                  "We received an error, but we still got data, "
00581                  "so we ignore the error here");
00582       }
00583       else {
00584         DBG_INFO(GWEN_LOGDOMAIN, "No message received (%d)", rv);
00585         GWEN_Gui_ProgressLog(sess->guiid,
00586                              GWEN_LoggerLevel_Error,
00587                              I18N("No message received"));
00588         return rv;
00589       }
00590     }
00591     else {
00592       DBG_INFO(GWEN_LOGDOMAIN, "No message received (%d)", rv);
00593       GWEN_Gui_ProgressLog(sess->guiid,
00594                            GWEN_LoggerLevel_Error,
00595                            I18N("No message received"));
00596       return rv;
00597     }
00598   }
00599 
00600   /* check for status and log it */
00601   db=GWEN_Io_LayerHttp_GetDbStatusIn(sess->ioLayer);
00602   code=GWEN_DB_GetIntValue(db, "code", 0, 0);
00603   if (code) {
00604     GWEN_BUFFER *lbuf;
00605     char sbuf[32];
00606     const char *text;
00607 
00608     lbuf=GWEN_Buffer_new(0, 64, 0, 1);
00609     GWEN_Buffer_AppendString(lbuf, "HTTP-Status: ");
00610     snprintf(sbuf, sizeof(sbuf)-1, "%d", code);
00611     sbuf[sizeof(sbuf)-1]=0;
00612     GWEN_Buffer_AppendString(lbuf, sbuf);
00613     text=GWEN_DB_GetCharValue(db, "text", 0, NULL);
00614     if (text) {
00615       GWEN_Buffer_AppendString(lbuf, " (");
00616       GWEN_Buffer_AppendString(lbuf, text);
00617       GWEN_Buffer_AppendString(lbuf, ")");
00618     }
00619     DBG_DEBUG(GWEN_LOGDOMAIN, "Status: %d (%s)",
00620               code, text);
00621     if (code<200 || code>299) {
00622       /* response is only ok for continuation (100) code */
00623       if (code!=100) {
00624         GWEN_DB_NODE *dbHeaderIn;
00625 
00626         dbHeaderIn=GWEN_Io_LayerHttp_GetDbHeaderIn(sess->ioLayer);
00627         DBG_ERROR(GWEN_LOGDOMAIN,
00628                   "Got an error response (%d: %s)",
00629                   code, text);
00630         GWEN_Gui_ProgressLog(sess->guiid,
00631                              GWEN_LoggerLevel_Error,
00632                              GWEN_Buffer_GetStart(lbuf));
00633         GWEN_Buffer_Reset(lbuf);
00634 
00635         if (code==301 || code==303 || code==305 || code==307) {
00636           /* moved */
00637           if (dbHeaderIn) {
00638             const char *s;
00639 
00640             s=GWEN_DB_GetCharValue(dbHeaderIn, "Location", 0, 0);
00641             if (s) {
00642               switch(code) {
00643               case 301:
00644               case 303:
00645                 GWEN_Buffer_AppendString(lbuf,
00646                                          I18N("HTTP: Moved permanently"));
00647                 break;
00648               case 305:
00649                 GWEN_Buffer_AppendString(lbuf,
00650                                          I18N("HTTP: Use proxy"));
00651                 break;
00652               case 307:
00653                 GWEN_Buffer_AppendString(lbuf,
00654                                          I18N("HTTP: Moved temporarily"));
00655                 break;
00656               default:
00657                 GWEN_Buffer_AppendString(lbuf,
00658                                          I18N("HTTP: Moved"));
00659               } /* switch */
00660               GWEN_Buffer_AppendString(lbuf, " (");
00661               GWEN_Buffer_AppendString(lbuf, s);
00662               GWEN_Buffer_AppendString(lbuf, ")");
00663 
00664               GWEN_Gui_ProgressLog(sess->guiid,
00665                                    GWEN_LoggerLevel_Warning,
00666                                    GWEN_Buffer_GetStart(lbuf));
00667             }
00668           }
00669         }
00670       }
00671       else {
00672         GWEN_Gui_ProgressLog(sess->guiid,
00673                              GWEN_LoggerLevel_Notice,
00674                              GWEN_Buffer_GetStart(lbuf));
00675       }
00676     }
00677     else {
00678       GWEN_Gui_ProgressLog(sess->guiid,
00679                            GWEN_LoggerLevel_Info,
00680                            GWEN_Buffer_GetStart(lbuf));
00681     }
00682     GWEN_Buffer_free(lbuf);
00683   }
00684   else {
00685     DBG_ERROR(GWEN_LOGDOMAIN, "No HTTP status code received");
00686     GWEN_Gui_ProgressLog(sess->guiid,
00687                          GWEN_LoggerLevel_Error,
00688                          I18N("No HTTP status code received"));
00689     code=GWEN_ERROR_BAD_DATA;
00690   }
00691 
00692   return code;
00693 }
00694 
00695 
00696 
00697 int GWEN_HttpSession_RecvPacket(GWEN_HTTP_SESSION *sess,
00698                                 GWEN_BUFFER *buf, int timeout) {
00699   int rv;
00700   uint32_t pos;
00701 
00702   /* read response */
00703   pos=GWEN_Buffer_GetPos(buf);
00704   for (;;) {
00705     GWEN_Gui_ProgressLog(sess->guiid,
00706                          GWEN_LoggerLevel_Info,
00707                          I18N("Waiting for response..."));
00708     rv=GWEN_HttpSession__RecvPacket(sess, buf, timeout);
00709     if (rv<0 || rv<200 || rv>299) {
00710       DBG_INFO(GWEN_LOGDOMAIN,
00711                "Error receiving packet (%d)", rv);
00712       GWEN_Io_Layer_DisconnectRecursively(sess->ioLayer, NULL,
00713                                           GWEN_IO_REQUEST_FLAGS_FORCE,
00714                                           sess->guiid, 2000);
00715       return rv;
00716     }
00717     if (rv!=100)
00718       break;
00719     GWEN_Gui_ProgressLog(sess->guiid,
00720                          GWEN_LoggerLevel_Info,
00721                          I18N("Received continuation response."));
00722     GWEN_Buffer_Crop(buf, 0, pos);
00723   }
00724 
00725   GWEN_Gui_ProgressLog(sess->guiid,
00726                        GWEN_LoggerLevel_Info,
00727                        I18N("Response received."));
00728 
00729   /* disconnect */
00730   GWEN_Gui_ProgressLog(sess->guiid,
00731                        GWEN_LoggerLevel_Info,
00732                        I18N("Disconnecting from server..."));
00733   GWEN_Io_Layer_DisconnectRecursively(sess->ioLayer, NULL,
00734                                       GWEN_IO_REQUEST_FLAGS_FORCE,
00735                                       sess->guiid, 2000);
00736   GWEN_Gui_ProgressLog(sess->guiid,
00737                        GWEN_LoggerLevel_Info,
00738                        I18N("Disconnected."));
00739 
00740   return 0;
00741 }
00742 
00743 
00744 
00745 int GWEN_HttpSession_ConnectionTest(GWEN_HTTP_SESSION *sess) {
00746   int rv;
00747 
00748   assert(sess);
00749   assert(sess->usage);
00750 
00751   /* first connect to server */
00752   GWEN_Gui_ProgressLog(sess->guiid,
00753                        GWEN_LoggerLevel_Notice,
00754                        I18N("Connecting to server..."));
00755   rv=GWEN_Io_Layer_ConnectRecursively(sess->ioLayer, NULL, 0,
00756                                       sess->guiid, 30000);
00757   if (rv==GWEN_ERROR_SSL) {
00758     GWEN_IO_LAYER *ioTls;
00759 
00760     /* try again with alternated SSLv3 flag */
00761     DBG_NOTICE(GWEN_LOGDOMAIN,
00762                "SSL-Error connecting (%d), retrying", rv);
00763     GWEN_Io_Layer_DisconnectRecursively(sess->ioLayer, NULL,
00764                                         GWEN_IO_REQUEST_FLAGS_FORCE,
00765                                         sess->guiid, 2000);
00766     ioTls=GWEN_Io_Layer_FindBaseLayerByType(sess->ioLayer,
00767                                             GWEN_IO_LAYER_TLS_TYPE);
00768     assert(ioTls);
00769 
00770     if (sess->flags & GWEN_HTTP_SESSION_FLAGS_FORCE_SSL3) {
00771       DBG_INFO(GWEN_LOGDOMAIN, "Retrying to connect (non-SSLv3)");
00772       GWEN_Gui_ProgressLog(sess->guiid,
00773                            GWEN_LoggerLevel_Info,
00774                            I18N("Retrying to connect (non-SSLv3)"));
00775       GWEN_Io_Layer_SubFlags(ioTls, GWEN_IO_LAYER_TLS_FLAGS_FORCE_SSL_V3);
00776       rv=GWEN_Io_Layer_ConnectRecursively(sess->ioLayer, NULL, 0,
00777                                           sess->guiid, 30000);
00778       if (rv==0) {
00779         GWEN_HttpSession_SubFlags(sess, GWEN_HTTP_SESSION_FLAGS_FORCE_SSL3);
00780       }
00781     }
00782     else {
00783       DBG_INFO(GWEN_LOGDOMAIN, "Retrying to connect (SSLv3)");
00784       GWEN_Gui_ProgressLog(sess->guiid,
00785                            GWEN_LoggerLevel_Info,
00786                            I18N("Retrying to connect (SSLv3)"));
00787       GWEN_Io_Layer_AddFlags(ioTls, GWEN_IO_LAYER_TLS_FLAGS_FORCE_SSL_V3);
00788       rv=GWEN_Io_Layer_ConnectRecursively(sess->ioLayer, NULL, 0,
00789                                           sess->guiid, 30000);
00790       if (rv==0) {
00791         GWEN_HttpSession_AddFlags(sess, GWEN_HTTP_SESSION_FLAGS_FORCE_SSL3);
00792       }
00793     }
00794   }
00795 
00796   if (rv<0) {
00797     DBG_INFO(GWEN_LOGDOMAIN, "Could not connect to server (%d)", rv);
00798     GWEN_Gui_ProgressLog(sess->guiid,
00799                          GWEN_LoggerLevel_Error,
00800                          I18N("Could not connect to server"));
00801     GWEN_Io_Layer_DisconnectRecursively(sess->ioLayer, NULL,
00802                                         GWEN_IO_REQUEST_FLAGS_FORCE,
00803                                         sess->guiid, 2000);
00804     return rv;
00805   }
00806   else {
00807     GWEN_Gui_ProgressLog(sess->guiid,
00808                          GWEN_LoggerLevel_Info,
00809                          I18N("Connected."));
00810 
00811     GWEN_Io_Layer_DisconnectRecursively(sess->ioLayer, NULL,
00812                                         GWEN_IO_REQUEST_FLAGS_FORCE,
00813                                         sess->guiid, 2000);
00814 
00815     return 0;
00816   }
00817 }
00818 
00819 
00820 
00821 

Generated on Sat Jan 2 09:32:35 2010 for gwenhywfar by  doxygen 1.6.1