iomanager.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  $RCSfile$
00003                              -------------------
00004     cvs         : $Id: crypttoken.h 1113 2007-01-10 09:14:16Z martin $
00005     begin       : Wed Mar 16 2005
00006     copyright   : (C) 2005 by Martin Preuss
00007     email       : martin@libchipcard.de
00008 
00009  ***************************************************************************
00010  *          Please see toplevel file COPYING for license details           *
00011  ***************************************************************************/
00012 
00013 #ifdef HAVE_CONFIG_H
00014 # include <config.h>
00015 #endif
00016 
00017 
00018 #include "iomanager_l.h"
00019 #include "iolayer_l.h"
00020 
00021 #include "i18n_l.h"
00022 #include <gwenhywfar/misc.h>
00023 #include <gwenhywfar/debug.h>
00024 #include <gwenhywfar/gui.h>
00025 #include <gwenhywfar/gwentime.h>
00026 
00027 #include <assert.h>
00028 
00029 #include <gnutls/gnutls.h>
00030 
00031 
00032 
00033 static GWEN_IO_LAYER_LIST *ioLayerList=NULL;
00034 
00035 
00036 
00037 int GWEN_Io_Manager_ModuleInit() {
00038   ioLayerList=GWEN_Io_Layer_List_new();
00039 
00040   gnutls_global_init();
00041 
00042   return 0;
00043 }
00044 
00045 
00046 
00047 int GWEN_Io_Manager_ModuleFini() {
00048   if (ioLayerList) {
00049     GWEN_Io_Layer_List_free(ioLayerList);
00050     ioLayerList=NULL;
00051   }
00052 
00053   gnutls_global_deinit();
00054 
00055   return 0;
00056 }
00057 
00058 
00059 
00060 int GWEN_Io_Manager_RegisterLayer(GWEN_IO_LAYER *io) {
00061   GWEN_IO_LAYER *p;
00062 
00063   /* check whether the given layer exists in our list */
00064   p=GWEN_Io_Layer_List_First(ioLayerList);
00065   while(p) {
00066     if (p==io) {
00067       DBG_INFO(GWEN_LOGDOMAIN, "IO Layer %p already registered", (void*)io);
00068       return GWEN_ERROR_INVALID;
00069     }
00070     p=GWEN_Io_Layer_List_Next(p);
00071   }
00072 
00073   GWEN_Io_Layer_List_Add(io, ioLayerList);
00074   //GWEN_Io_Layer_Attach(io);
00075   GWEN_Io_Layer_AddFlags(io, GWEN_IO_LAYER_FLAGS_REGISTERED);
00076   return 0;
00077 }
00078 
00079 
00080 
00081 int GWEN_Io_Manager_UnregisterLayer(GWEN_IO_LAYER *io) {
00082   GWEN_IO_LAYER *p;
00083 
00084   /* check whether the given layer exists in our list */
00085   p=GWEN_Io_Layer_List_First(ioLayerList);
00086   while(p) {
00087     if (p==io)
00088       break;
00089     p=GWEN_Io_Layer_List_Next(p);
00090   }
00091 
00092   if (p!=io) {
00093     DBG_INFO(GWEN_LOGDOMAIN, "IO Layer %p not registered", (void*)io);
00094     return GWEN_ERROR_INVALID;
00095   }
00096 
00097   GWEN_Io_Layer_SubFlags(io, GWEN_IO_LAYER_FLAGS_REGISTERED);
00098   GWEN_Io_Layer_List_Del(io);
00099   //GWEN_Io_Layer_free(io);
00100 
00101   return 0;
00102 }
00103 
00104 
00105 
00106 GWEN_IO_LAYER_WORKRESULT GWEN_Io_Manager_Work(void) {
00107   int anythingDone=0;
00108   int i;
00109 
00110   for (i=0;i<10;i++) {
00111     GWEN_IO_LAYER *p;
00112     int somethingDone=0;
00113 
00114     p=GWEN_Io_Layer_List_First(ioLayerList);
00115     while(p) {
00116       GWEN_IO_LAYER_WORKRESULT res;
00117 
00118       res=GWEN_Io_Layer_WorkOnRequests(p);
00119       if (res==GWEN_Io_Layer_WorkResultOk)
00120         somethingDone=1;
00121 
00122       p=GWEN_Io_Layer_List_Next(p);
00123     }
00124     if (somethingDone)
00125       anythingDone++;
00126     else
00127       break;
00128   }
00129 
00130   return anythingDone?GWEN_Io_Layer_WorkResultOk:GWEN_Io_Layer_WorkResultBlocking;
00131 }
00132 
00133 
00134 
00135 int GWEN_Io_Manager_Wait(int msecs, uint32_t guiid) {
00136   GWEN_IO_LAYER *p;
00137   GWEN_SOCKET_LIST2 *readSockets;
00138   GWEN_SOCKET_LIST2 *writeSockets;
00139   int rv;
00140 
00141   /* populate socket lists */
00142   readSockets=GWEN_Socket_List2_new();
00143   writeSockets=GWEN_Socket_List2_new();
00144 
00145   p=GWEN_Io_Layer_List_First(ioLayerList);
00146   while(p) {
00147     GWEN_Io_Layer_AddWaitingSockets(p, readSockets, writeSockets);
00148     p=GWEN_Io_Layer_List_Next(p);
00149   }
00150 
00151   rv=GWEN_Gui_WaitForSockets(readSockets, writeSockets, guiid, msecs);
00152   GWEN_Socket_List2_free(writeSockets);
00153   GWEN_Socket_List2_free(readSockets);
00154 
00155   if (rv) {
00156     if (rv!=GWEN_ERROR_EOF) {
00157       DBG_INFO(GWEN_LOGDOMAIN, "WAITFORSOCKETS: %d", rv);
00158     }
00159   }
00160 
00161   return rv;
00162 }
00163 
00164 
00165 
00166 int GWEN_Io_Manager_WaitForRequest(GWEN_IO_REQUEST *r, int msecs) {
00167   GWEN_TIME *t0;
00168   uint32_t progressId;
00169   uint64_t timeout;
00170   const char *s;
00171   GWEN_IO_LAYER_WORKRESULT res;
00172 
00173   if (GWEN_Io_Request_GetStatus(r)==GWEN_Io_Request_StatusFinished) {
00174     /* request already finished */
00175     return 0;
00176   }
00177 
00178   if (msecs==GWEN_TIMEOUT_NONE) {
00179     /* no timeout, return immediately */
00180     DBG_INFO(GWEN_LOGDOMAIN, "No timeout, returning immediately");
00181     return GWEN_ERROR_TIMEOUT;
00182   }
00183 
00184   /* first shot: in many cases one work call is enough */
00185   res=GWEN_Io_Manager_Work();
00186   if (GWEN_Io_Request_GetStatus(r)==GWEN_Io_Request_StatusFinished) {
00187     return 0;
00188   }
00189 
00190   /* ok, we have to go the long way */
00191   t0=GWEN_CurrentTime();
00192   assert(t0);
00193 
00194   if (msecs==GWEN_TIMEOUT_NONE ||
00195       msecs==GWEN_TIMEOUT_FOREVER)
00196     timeout=0;
00197   else
00198     timeout=msecs;
00199 
00200   switch(GWEN_Io_Request_GetType(r)) {
00201   case GWEN_Io_Request_TypeConnect:
00202     s=I18N("Connecting...");
00203     break;
00204   case GWEN_Io_Request_TypeDisconnect:
00205     s=I18N("Disconnecting...");
00206     break;
00207   case GWEN_Io_Request_TypeRead:
00208     s=I18N("Reading...");
00209     break;
00210   case GWEN_Io_Request_TypeWrite:
00211     s=I18N("Writing...");
00212     break;
00213   default:
00214     s=I18N("Waiting for request to finish...");
00215   }
00216 
00217   progressId=GWEN_Gui_ProgressStart(GWEN_GUI_PROGRESS_DELAY |
00218                                     GWEN_GUI_PROGRESS_ALLOW_EMBED |
00219                                     GWEN_GUI_PROGRESS_SHOW_PROGRESS |
00220                                     GWEN_GUI_PROGRESS_SHOW_ABORT,
00221                                     s,
00222                                     NULL,
00223                                     timeout,
00224                                     GWEN_Io_Request_GetGuiId(r));
00225 
00226   for (;;) {
00227     int rv;
00228     int i;
00229     int shortTimeout=msecs;
00230 
00231     /* first: work as long as we can /and check status on the way) */
00232     for (i=0; i<10000; i++) {
00233       if (GWEN_Io_Request_GetStatus(r)==GWEN_Io_Request_StatusFinished) {
00234         /* request finished */
00235         GWEN_Gui_ProgressEnd(progressId);
00236         GWEN_Time_free(t0);
00237         return 0;
00238       }
00239       res=GWEN_Io_Manager_Work();
00240       if (res==GWEN_Io_Layer_WorkResultBlocking)
00241         break;
00242       if (res==GWEN_Io_Layer_WorkResultError) {
00243         DBG_INFO(GWEN_LOGDOMAIN, "IO error (res=%d)", res);
00244         GWEN_Gui_ProgressLog(progressId,
00245                              GWEN_LoggerLevel_Error,
00246                              I18N("IO error"));
00247         GWEN_Gui_ProgressEnd(progressId);
00248         GWEN_Time_free(t0);
00249         return GWEN_ERROR_IO;
00250       }
00251     }
00252 
00253     if (msecs!=GWEN_TIMEOUT_FOREVER) {
00254       GWEN_TIME *t1;
00255       int d;
00256 
00257       /* check for timeout */
00258       t1=GWEN_CurrentTime();
00259       assert(t1);
00260       d=(int)GWEN_Time_Diff(t1, t0);
00261       GWEN_Time_free(t1);
00262       if (d>=msecs) {
00263         DBG_INFO(GWEN_LOGDOMAIN, "Timeout (%d>%d)", d, msecs);
00264         GWEN_Gui_ProgressEnd(progressId);
00265         GWEN_Time_free(t0);
00266         return GWEN_ERROR_TIMEOUT;
00267       }
00268       /* calculate remaining time */
00269       shortTimeout=msecs-d;
00270     }
00271 
00272     /* if still not blocking (i.e. there still are things to do) we might have an error in one
00273      * of the io layers (e.g. an ioi layer always reports non-blocking even though it had nothing
00274      * left to do)
00275      */
00276     if (res!=GWEN_Io_Layer_WorkResultBlocking) {
00277       /* sleep for a feew ms if the result is still non-blocking */
00278       DBG_WARN(GWEN_LOGDOMAIN, "Still working after %d loops, sleeping", i);
00279       GWEN_Socket_Select(NULL, NULL, NULL, GWEN_GUI_CPU_TIMEOUT);
00280     }
00281     else {
00282       /* wait for changes on sockets */
00283       rv=GWEN_Io_Manager_Wait(shortTimeout, progressId);
00284       if (rv!=0 && rv!=GWEN_ERROR_TIMEOUT) {
00285         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00286         GWEN_Gui_ProgressLog(progressId,
00287                              GWEN_LoggerLevel_Error,
00288                              I18N("IO error"));
00289         GWEN_Gui_ProgressEnd(progressId);
00290         GWEN_Time_free(t0);
00291         return rv;
00292       }
00293     }
00294   } /* for */
00295 }
00296 
00297 
00298 
00299 
00300 
00301 

Generated on Fri Apr 11 01:53:47 2008 for gwenhywfar by  doxygen 1.5.5